J'essaie de lire l'API Yelp. Voici mon code.
public async Task<Common.Models.Yelp.Yelp> GetAllBusiness(decimal latitude, decimal longitude) { var all = await _webPortalApiClient.InvokeApi($"businesses/search?limit=10&latitude={latitude}&longitude={longitude}", HttpAction.Get, null, null, "https://api.yelp.com/v3/"); if (all == null) { return null; } //var business = await all.ReadAsAsync<Common.Models.Yelp.Yelp>(); var business = all.ReadAsAsync<Object>().Result; var result = (Common.Models.Yelp.Yelp)(business); return result; }
J'appelle la fonction ci-dessus comme
public async Task<HttpContent> InvokeApi(string path, HttpAction action, HttpContent content = null, TimeSpan? overrideTimeout = null, string externalServer = null) { var sUrl = externalServer == null ? ServerUrl : externalServer; using (var client = new HttpClient()) { client.BaseAddress = new Uri(sUrl); if (overrideTimeout.HasValue) { client.Timeout = overrideTimeout.Value; } //this.Log("Connecting to {0} Api at {1}".Fmt(WebPortalServer, ServerUrl)); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", AccessToken); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response; switch (action) { case HttpAction.Get: response = await client.GetAsync(path); break; case HttpAction.Post: response = await client.PostAsync(path, content); break; case HttpAction.Put: response = await client.PutAsync(path, content); break; case HttpAction.Delete: response = await client.DeleteAsync(path); break; default: throw new ArgumentOutOfRangeException("action", action, null); } return response.IsSuccessStatusCode ? response.Content : null; } }
La réponse que j'obtiens de cette API est intégrée dans curly accolades, à cause de cela, il ne me permet pas de convertir la réponse en modèle Yelp.
C'est la réponse que j'obtiens.
{{"entreprises": [{"id": "Xg-FyjVKAN70LO4u4Z1ozg", "alias": "hog-island-oyster-co-san-francisco", "name": "Hog Island Oyster Co", "image_url": "", "is_closed": false, "url ":" "," review_count ": 5550," categories ": [{" alias ":" seafood "," title ":" Seafood "}, {" alias ":" seafoodmarkets "," title ":" Seafood Markets "}, {" alias ":" raw_food "," title ":" Live / Raw Food "}]," rating ": 4,5," coordonnées ": {" latitude ": 37.795831," longitude ": -122.393303}, "transactions": [], "price": "$$", "location": {"address1": "1 Ferry Bldg", "address2": "", "address3": "Shop 11", "city": "San Francisco", "zip_code": "94111", "country": "US", "state": "CA", " display_address ": [" 1 Ferry Bldg "," Shop 11 "," San Francisco, CA 94111 "]}," phone ":" +14153917117 "," display_phone ":" (415) 391-7117 "," distance " : 1154.8167382059307}, {"id": "PsY5DMHxa5iNX_nX0T-qPA", "alias": "kokkari-estiatorio-san-francisco", "name": "Kokkari Estiatorio", "image_url": "", "is_closed": false , "url": "", "review_count": 4300, "categories": [{"alias": "greek", "title": "Greek"}, {"alias": "méditerranéen", "title": "Méditerranée"}], "note": 4.5, "coordonnées": {"latitude": 37.796996, "longitude": -122.399661}, "transactions": ["ramassage"], "prix": "$$$" , "lieu": { "address1": "200 Jackson St", "address2": "", "address3": "", "city": "San Francisco", "zip_code": "94111", "country": "US", " state ":" CA "," display_address ": [" 200 Jackson St "," San Francisco, CA 94111 "]}," phone ":" +14159810983 "," display_phone ":" (415) 981-0983 ", "distance": 1124.9562174585888}, {"id": "ZoZjbOYR-apY8XvommlNUA", "alias": "the-house-san-francisco", "name": "The House", "image_url": "": false, "url": "", "review_count": 4521, "categories": []}}
Il y a une paire d'accolades supplémentaires au début et à la fin de la réponse. Comment puis-je récupérer la réponse au format Json approprié.
3 Réponses :
L'appel de
var business = await all.ReadAsAsync<object>(); return ((JObject)business).ToObject<Yelp>();
vous renvoie une instance de JObject
qui n'est pas convertible en Yelp
par simple diffusion. Appelez plutôt ReadAsAsync
comme ceci
var business = await all.ReadAsAsync<Common.Models.Yelp.Yelp>(); return business;
Si vous voulez toujours l'appeler avec object
, vous pouvez le faire comme ceci
all.ReadAsAsync<Object>().Result;
Remarque
La réponse json ne contient pas d'accolades supplémentaires. Il suffit JObject
de les ajouter dans la vue de débogage. Il est facile de vérifier cela en examinant le résultat de la lecture de la réponse sous forme de chaîne all.ReadAsStringAsync().Result
.
en fait, il doit être correctement asynchrone: var business = wait all.ReadAsAsync
J'ai essayé la solution ci-dessus mais j'obtiens l'erreur ci-dessous {"Message": "Une erreur s'est produite.", "ExceptionMessage": "La chaîne d'entrée '4.5' n'est pas un entier valide. Chemin 'business [0] .rating', ligne 1, position 634. "," ExceptionType ":" Newtonsoft.Json.JsonReaderException "," StackTrace ":" à Newtonsoft.Json.JsonTextReader.ParseReadNumber (ReadType readType, Char firstChar, Int32 initialPosition) \ r \ n à Newtonsoft. Json.JsonTextReader.ParseNumber (ReadType readType) \ r \ n à .......}
var business = all.Result; var resultString = business.ReadAsStringAsync(); return JsonConvert.DeserializeObject<Common.Models.Yelp.Yelp>(resultString);
Bonjour et bienvenue sur Stack Overflow. Il est recommandé d'ajouter plus de contexte (pourquoi le problème était là ou pourquoi cela fonctionne et en quoi consiste le code qui corrige le problème) à votre réponse pour qu'elle soit plus facilement comprise par l'OP et les autres qui s'en approchent.
Utilisez la méthode de désérialisation de JSON.NET pour désérialiser de la chaîne dans votre POCO souhaité en utilisant la surcharge de type générique.
public async Task<HttpContent> InvokeApi(string path, HttpAction action, HttpContent content = null, TimeSpan? overrideTimeout = null, string externalServer = null) { var sUrl = externalServer == null ? ServerUrl : externalServer; using (var client = new HttpClient()) { client.BaseAddress = new Uri(sUrl); if (overrideTimeout.HasValue) { client.Timeout = overrideTimeout.Value; } //this.Log("Connecting to {0} Api at {1}".Fmt(WebPortalServer, ServerUrl)); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", AccessToken); client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response; switch (action) { case HttpAction.Get: response = await client.GetAsync(path); break; case HttpAction.Post: response = await client.PostAsync(path, content); break; case HttpAction.Put: response = await client.PutAsync(path, content); break; case HttpAction.Delete: response = await client.DeleteAsync(path); break; default: throw new ArgumentOutOfRangeException("action", action, null); } return response.IsSuccessStatusCode ? response.Content : null; } } public async Task<Common.Models.Yelp.Yelp> GetAllBusiness(decimal latitude, decimal longitude) { HttpContent all = await _webPortalApiClient.InvokeApi($"businesses/search?limit=10&latitude={latitude}&longitude={longitude}", HttpAction.Get, null, null, "https://api.yelp.com/v3/"); if (all == null) { return null; } string responseBody = await all.ReadAsStringAsync(); // Deserialize from serialized string into your POCO var business = JsonConvert.DeserializeObject<Common.Models.Yelp.Yelp>(responseBody); return business; }
Remarque: faites de votre HttpClient un singleton.
Le Json publié est de toute façon invalide. Le double
{}
peut être un cas de double encodage, ou une enveloppe manquante.utilisez async:
var business = wait all.ReadAsAsync