Десериализация вызова API для объекта не работает в List - PullRequest
0 голосов
/ 03 октября 2019

Я пытаюсь вызвать API с помощью HttpClient и десериализовать JSON в объект ответа. В этом JSON есть список объектов вопроса пустяков. Когда я устанавливаю объект в десериализованный объект, список остается пустым.

Я проверил, работает ли HttpClient, да, я также попытался использовать JsonConvert.

Это TriviaQuestion и Responseклассы:

public class TriviaQuestion
{
    public string Category { get; set; }
    public string Type { get; set; }
    public string Difficulty { get; set; }
    public string Question { get; set; }
    public string CorrectAnswer { get; set; }
    public List<string> IncorrectAnswers { get; set; }

    public override string ToString()
    {
        return $"Question: {Question}";
    }
}

public class Response
{
    public int ResponseCode { get; set; }
    public List<TriviaQuestion> Questions { get; set; }

    public Response()
    {
        Questions = new List<TriviaQuestion>();
    }
}

Это код для десериализации

private static HttpClient client = new HttpClient();
private static string URL = "https://opentdb.com/api.php";
private static string urlParameters = "?amount=1";

static void Main()
{
    RunAsync().GetAwaiter().GetResult();
}

static async Task RunAsync()
{
    client.BaseAddress = new Uri(URL);
    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(
       new MediaTypeWithQualityHeaderValue("application/json"));

    Response response = new Response();

    try
    {
        response = await GetResponseAsync(urlParameters);
        ShowResponse(response);
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }

    Console.ReadLine();
}

static async Task<Response> GetResponseAsync(string path)
{
    Response response = new Response();
    //string responseString = "";

    HttpResponseMessage httpResponse = await client.GetAsync(path);

    if (httpResponse.IsSuccessStatusCode)
    {
        //responseString = httpResponse.Content.ReadAsStringAsync().Result;
        response = await httpResponse.Content.ReadAsAsync<Response>();
    }

    //response = JsonConvert.DeserializeObject<Response>(responseString);
    return response;
}

Я ожидаю получить список объектов вопроса о пустяках, но список останется на счете = 0. Если я распечатываюjsonString я получаю это результат:

{
    "response_code":0,
    "results": [
    { 
        "category":"Entertainment: Video Games",
        "type":"multiple",
        "difficulty":"medium",
        "question":"In Need for Speed: Underground, what car does Eddie drive?",
        "correct_answer":"Nissan Skyline GT-R (R34)",
        "incorrect_answers": [
            "Mazda RX-7 FD3S",
            "Acura Integra Type R",
            "Subaru Impreza 2.5 RS"
        ]
    }]
}

Спасибо за помощь!

Ответы [ 2 ]

1 голос
/ 03 октября 2019

Ваш Response класс немного ошибочен. Он не соответствует JSON, который вы опубликовали.

public List<TriviaQuestion> Questions { get; set; }

должно быть:

public List<TriviaQuestion> Results { get; set; }

Кроме того, поскольку ваш JSON имеет корпус со змеей, для захвата response_code, correct_answer иincorrect_answers значений, которые вам понадобятся для украшения свойств вашего класса JsonProperty атрибутами, т.е. [JsonProperty(PropertyName = "incorrect_answers")], или вы можете использовать ContractResolver:

var contractResolver = new DefaultContractResolver
{
    NamingStrategy = new SnakeCaseNamingStrategy()
};

var response = JsonConvert.DeserializeObject<Response>(json, new JsonSerializerSettings
{
    ContractResolver = contractResolver
});

Таким образом, ваши полные классы будут:

public class TriviaQuestion
{
    public string Category { get; set; }

    public string Type { get; set; }

    public string Difficulty { get; set; }

    public string Question { get; set; }

    // only need this if not using the ContractResolver
    [JsonProperty(PropertyName = "correct_answer")]
    public string CorrectAnswer { get; set; }

    // only need this if not using the ContractResolver
    [JsonProperty(PropertyName = "incorrect_answers")]
    public List<string> IncorrectAnswers { get; set; }
}

public class Response
{
    // only need this if not using the ContractResolver
    [JsonProperty(PropertyName = "response_code")]  
    public int ResponseCode { get; set; }

    public List<TriviaQuestion> Results { get; set; }
}

Тогда вы сможете десериализовать:

var json = "{\r\n    \"response_code\":0,\r\n    \"results\": [\r\n    { \r\n        \"category\":\"Entertainment: Video Games\",\r\n        \"type\":\"multiple\",\r\n        \"difficulty\":\"medium\",\r\n        \"question\":\"In Need for Speed: Underground, what car does Eddie drive?\",\r\n        \"correct_answer\":\"Nissan Skyline GT-R (R34)\",\r\n        \"incorrect_answers\": [\r\n            \"Mazda RX-7 FD3S\",\r\n            \"Acura Integra Type R\",\r\n            \"Subaru Impreza 2.5 RS\"\r\n        ]\r\n    }]\r\n}";

// if using JsonProperty attributes
var response = JsonConvert.DeserializeObject<Response>(json);

// or 

// if using ContractResolver
var contractResolver = new DefaultContractResolver
{
    NamingStrategy = new SnakeCaseNamingStrategy()
};

var response = JsonConvert.DeserializeObject<Response>(json, new JsonSerializerSettings
{
    ContractResolver = contractResolver
});
0 голосов
/ 03 октября 2019

возвращенный JSON в ответ:

var json = await httpResponse.Content.ReadAsStringAsync();
response= JsonConvert.DeserializeObject<Response>(json);
...