JsonConvert.DeserializeObject 生成空动态对象
JsonConvert.DeserializeObject generates a null dynamic object
我正在尝试使用 JSON.NET 反序列化来自 REST API 的响应。
dynamic resultObject = JsonConvert.DeserializeObject(responseText);
我不想为 REST API returns 的不同类型的响应定义 类,因为它经常变化。我想利用 dynamic
运行 时间变量。
在 VS2015 中,我添加了观察者以在上面的代码行执行后直接查看值。
resultObject
解析为 null 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()
的响应,但变量仍设置为空。
我认为,JSonConvert 无法解决您的任务。您可以简单地使用 JObject and JObject.Parse and then iterate "errors" property by Item
你的问题是,在下一行中,你假设 "errors"
是 JSON objects 的数组,每个对象都有一个 属性 命名为 "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 to JSON, specifically the SelectTokens()
along with the 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.
示例 fiddle.
我正在尝试使用 JSON.NET 反序列化来自 REST API 的响应。
dynamic resultObject = JsonConvert.DeserializeObject(responseText);
我不想为 REST API returns 的不同类型的响应定义 类,因为它经常变化。我想利用 dynamic
运行 时间变量。
在 VS2015 中,我添加了观察者以在上面的代码行执行后直接查看值。
resultObject
解析为 null 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()
的响应,但变量仍设置为空。
我认为,JSonConvert 无法解决您的任务。您可以简单地使用 JObject and JObject.Parse and then iterate "errors" property by Item
你的问题是,在下一行中,你假设 "errors"
是 JSON objects 的数组,每个对象都有一个 属性 命名为 "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 to JSON, specifically the SelectTokens()
along with the 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.
示例 fiddle.