JsonConvert.DeserializeObject生成一个空动态对象

本文关键字:一个 动态 对象 DeserializeObject JsonConvert | 更新日期: 2023-09-27 18:05:35

我正在尝试使用JSON.NET反序列化来自REST API的响应。

dynamic resultObject = JsonConvert.DeserializeObject(responseText);

我不想为REST API返回的不同类型的响应定义类,因为它经常变化。我想利用dynamic运行时变量。

在VS2015中,我添加了观察者来直接在上面的代码行执行后查看值。

resultObject解析为空object,然而,监视器显示行代码运行直接导致Newtonsoft.Json.Linq.JObject被反序列化的响应字符串填充。

为什么动态变量resultObject不与JObject一起填充?

            var responseStream = e.Response?.GetResponseStream();
            string responseText = "";
            if (responseStream != null)
            {
                using (var reader = new StreamReader(responseStream))
                {
                    responseText = reader.ReadToEnd();
                }
                dynamic responseObject = JsonConvert.DeserializeObject(responseText); 
                foreach (var error in responseObject["errors"].Children())
                {
                     errors.Add(error.Val);
                }
            }

更新:

要解析的JSON内容:

JSON更新以删除调试信息-问题仍然存在。

https://jsonblob.com/57cb00c7e4b0dc55a4f2abe9

更新2:

似乎JsonConvert.DeserializeObject()正在解析我的JSON在整个对象周围有额外的括号。

从响应流生成的字符串:

"{'"message'":'"422 Unprocessable Entity'",'"errors'":[['"The email must be a valid email address.'"],['"The password must be at least 8 characters.'"]],'"status_code'":422}"

JsonConvert.DeserializeObject():

{{ "message": "422 Unprocessable Entity", "errors": [ [ "The email must be a valid email address." ], [ "The password must be at least 8 characters." ] ], "status_code": 422 }}

更新3:

转换为JObject.Parse会产生相同的输出。

我将变量从类型dynamic更改为JObject -以接受JObject.Parse()的响应,并且仍然将变量设置为null。

JsonConvert.DeserializeObject生成一个空动态对象

我认为,JSonConvert是无效的解决您的任务。您可以简单地使用JObject和JObject。通过Item

解析并迭代"errors"属性

您的问题是,在下一行中,您假设"errors"是JSON 对象的数组,每个对象都有一个名为"Val"的属性:

foreach (var error in responseObject["errors"].Children())
{
     errors.Add(error.Val);
}

然而,"errors"实际上是一个数组数组,因此error.Val的计算结果为null。相反,您需要这样做:

var errors = new List<string>();
dynamic responseObject = JsonConvert.DeserializeObject(responseText);
foreach (dynamic errorList in responseObject["errors"].Children())
{
    foreach (dynamic error in errorList.Children())
    {
        errors.Add((string)error);
    }
}
但是,我个人建议避免使用dynamic,因为您将失去静态编译时类型检查的优势。充满dynamic对象的代码也很难调试。相反,我建议使用LINQ到JSON,特别是SelectTokens()以及JSONPath递归下降运算符..*来挑选"errors"对象内的所有字符串值,如下所示:
var token = JToken.Parse(responseText);
var errors = token.SelectTokens("errors..*")    // Iterate through all descendants of the "errors" property
    .OfType<JValue>()                           // Filter those that are primitive values
    .Select(v => (string)v)                     // Convert to their string values
    .ToList();                                  // And evaluate the query as a list.

小提琴例子。