1
votes

Des accolades supplémentaires dans la réponse de l'API Web empêchent la réponse de se convertir en modèle

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 commentaires

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 ();


3 Réponses :


1
votes

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.


2 commentaires

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 à .......}



-1
votes
 var business = all.Result;  
 var resultString = business.ReadAsStringAsync();  
 return JsonConvert.DeserializeObject<Common.Models.Yelp.Yelp>(resultString);

1 commentaires

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.



0
votes

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;
}


0 commentaires