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}"
{{
"message": "422 Unprocessable Entity",
"errors": [
[
"The email must be a valid email address."
],
[
"The password must be at least 8 characters."
]
],
"status_code": 422
}}
转换为JObject.Parse
会产生相同的输出。
我将变量从类型dynamic
更改为JObject
-以接受JObject.Parse()
的响应,并且仍然将变量设置为null。
我认为,JSonConvert是无效的解决您的任务。您可以简单地使用JObject和JObject。通过Item
您的问题是,在下一行中,您假设"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.
小提琴例子。