我正在尝试使用Newtonsoft.Json反序列化嵌套在Json响应中的一些对象。我想将以下Jsons Term
对象反序列化为一个列表。我在Json响应中有很多Term
个对象,所以性能和紧凑性对我来说很重要。我也只想定义Term
类,因为我暂时不关心其他数据。
我为Term定义了一个模型:
public class Term
{
public string Known { get; set; }
public string Word { get; set; }
}
我的Json看起来像这样:
{
"myName":"Chris",
"mySpecies":"Cat",
"myTerms":
[
{
"Term":
{
"Known":"true",
"Word":"Meow"
}
},
{
"Term":
{
"Known":"false",
"Word":"Bark"
}
}
]
}
我的C#反序列化代码:
var response = await httpClient.GetAsync(uri);
string responseString = response.Content.ReadAsStringAsync().GetResults();
var searchTermList = JsonConvert.DeserializeObject<List<Term>>(responseString);
我收到的问题/错误是,我不确定如何从json响应中获取这些术语:
{Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current
JSON object (e.g. {"name":"value"}) into type
'System.Collections.Generic.List`1[CoreProject.Models.Term]' because
the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or
change the deserialized type so that it is a normal .NET type (e.g. not a
primitive type like integer, not a collection type like an array or List<T>)
that can be deserialized from a JSON object. JsonObjectAttribute can also be
added to the type to force it to deserialize from a JSON object.
任何建议都将不胜感激:)
答案 0 :(得分:3)
您收到该错误是因为您尝试将JSON反序列化为List<T>
某些T
(特别是Term
),但根JSON容器不是数组,它是一个对象 - 由{
和}
包围的一组无序的键/值对 - 包含与您的Term
对应的相当深的嵌入对象集合。
鉴于此,您可以使用http://json2csharp.com/或Paste JSON as Classes自动生成与您的JSON相对应的完整数据模型,然后反序列化到该模型并选择有趣的部分。
但是,如果您不想定义完整的数据模型,则可以通过将JSON加载到中间JToken
hierarchy然后使用来选择性地反序列化相关部分
SelectTokens()
:
var root = JToken.Parse(responseString);
var searchTermList = root.SelectTokens("myTerms[*].Term")
.Select(t => t.ToObject<Term>())
.ToList();
注意:
查询字符串"myTerms[*].Term"
包含JSONPath通配符运算符[*]
。此运算符匹配父元素"myTerms"
下的所有数组元素。
Json.NET支持Querying JSON with JSONPath中记录的JSONPath语法。
如果JSON比问题中显示的更复杂,则可以使用JSONPath递归下降运算符...
来查找JSON对象层次结构中任何级别的Term
个对象,例如:
var searchTermList = root.SelectTokens("..Term")
.Select(t => t.ToObject<Term>())
.ToList();
选择相关的JSON对象后,您可以使用Jtoken.ToObject<Term>()
将每个对象反序列化为最终的c#模型。
示例fiddle。
答案 1 :(得分:0)
试一试
public class Term
{
public string Known { get; set; }
public string Word { get; set; }
}
public class Response
{
public List<TermWrapper> MyTerms { get; set; }
}
public class TermWrapper
{
public Term Term { get; set; }
}
...
var response = await httpClient.GetAsync(uri);
string responseString = response.Content.ReadAsStringAsync().GetResults();
var searchTermList = JsonConvert
.DeserializeObject<Response>(responseString)
.MyTerms
.Select(x => x.Term);
您必须考虑JSON的完整结构。您有一个具有3个属性的对象。您感兴趣的是一个对象数组,但对象不是术语,它们是具有名为“Term”的属性的对象。该属性本身属于Term
类型。通过创建具有类似结构的类,您可以从结构中提取所有必要的数据。