反序列化 API 对对象的调用在 List 上不起作用

Deserializing API call to object doesn't work on List

我正在尝试使用 HttpClient 调用 API 并将 json 反序列化为响应对象。在这个 json 中,有一个 trivia 问题对象列表。当我将对象设置为反序列化对象时,列表保持为空。

我检查过 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"
        ]
    }]
}

感谢您的帮助!

返回的 JSON 变成响应:

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

你的Responseclass有点不对。它与您发布的 JSON 不匹配。

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

应该是:

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

此外,由于您的 JSON 有蛇形外壳,要捕获 response_codecorrect_answerincorrect_answers 值,您需要装饰 class 具有 JsonProperty 属性的属性,即 [JsonProperty(PropertyName = "incorrect_answers")] 或者您可以使用 ContractResolver:

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

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

因此您的完整 classes 将是:

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