C# 使用不同的数据结构反序列化JSON
我正在使用的一个JSON API返回的响应根据查询返回的结果的多少而改变其数据结构。我从C#中使用它,并使用JSON.NET对响应进行反序列化 下面是从API返回的JSON 多结果响应:C# 使用不同的数据结构反序列化JSON,c#,json,json.net,zoho,C#,Json,Json.net,Zoho,我正在使用的一个JSON API返回的响应根据查询返回的结果的多少而改变其数据结构。我从C#中使用它,并使用JSON.NET对响应进行反序列化 下面是从API返回的JSON 多结果响应: { "response": { "result": { "Leads": { "row": [ { "no": "1", ... ... ... { "response": { "result": {
{
"response": {
"result": {
"Leads": {
"row": [
{
"no": "1",
...
...
...
{
"response": {
"result": {
"Leads": {
"row": {
"no": "1",
...
...
...
public class ZohoLeadResponseRootJson
{
public ZohoLeadResponseJson Response { get; set; }
}
public class ZohoLeadResponseJson
{
public ZohoLeadResultJson Result { get; set; }
}
public class ZohoLeadResultJson
{
public ZohoDataMultiRowJson Leads { get; set; }
}
public class ZohoDataMultiRowJson
{
public List<ZohoDataRowJson> Row { get; set; }
}
public class ZohoDataRowJson
{
public int No { get; set; }
...
}
单一结果响应:
{
"response": {
"result": {
"Leads": {
"row": [
{
"no": "1",
...
...
...
{
"response": {
"result": {
"Leads": {
"row": {
"no": "1",
...
...
...
public class ZohoLeadResponseRootJson
{
public ZohoLeadResponseJson Response { get; set; }
}
public class ZohoLeadResponseJson
{
public ZohoLeadResultJson Result { get; set; }
}
public class ZohoLeadResultJson
{
public ZohoDataMultiRowJson Leads { get; set; }
}
public class ZohoDataMultiRowJson
{
public List<ZohoDataRowJson> Row { get; set; }
}
public class ZohoDataRowJson
{
public int No { get; set; }
...
}
请注意“row”节点的区别,在多个结果的情况下它是一个数组,在单个结果的情况下它是一个对象
下面是我用来反序列化这些数据的类
课程:
{
"response": {
"result": {
"Leads": {
"row": [
{
"no": "1",
...
...
...
{
"response": {
"result": {
"Leads": {
"row": {
"no": "1",
...
...
...
public class ZohoLeadResponseRootJson
{
public ZohoLeadResponseJson Response { get; set; }
}
public class ZohoLeadResponseJson
{
public ZohoLeadResultJson Result { get; set; }
}
public class ZohoLeadResultJson
{
public ZohoDataMultiRowJson Leads { get; set; }
}
public class ZohoDataMultiRowJson
{
public List<ZohoDataRowJson> Row { get; set; }
}
public class ZohoDataRowJson
{
public int No { get; set; }
...
}
公共类ZohoLeadResponseRootJson
{
公共zoholeadsresponsejson响应{get;set;}
}
公共类ZohoLeadResponseJson
{
public zoholeadsultjson结果{get;set;}
}
公共类ZohoLeadResultJson
{
公共ZohoDataMultiRowJson引线{get;set;}
}
公共类ZohoDataMultiRowJson
{
公共列表行{get;set;}
}
公共类ZohoDataRowJson
{
公共int No{get;set;}
...
}
“多结果响应”是反序列化的,没有任何问题,但是当响应中只有一个结果时,由于数据结构更改,响应无法反序列化。我有个例外
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON
object (e.g. {"name":"value"}) into type
'System.Collections.Generic.List`1[MyNamespace.ZohoDataRowJson]'
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.
Path 'response.result.Notes.row.no', line 1, position 44.
Newtonsoft.Json.JsonSerializationException:无法反序列化当前Json
对象(例如{“名称”:“值”})转换为类型
'System.Collections.Generic.List'1[MyNamespace.ZohoDataRowJson]'
因为该类型需要一个JSON数组(例如[1,2,3])才能正确反序列化。
要修复此错误,请将JSON更改为JSON数组(例如[1,2,3])
或者更改反序列化类型,使其成为正常的.NET类型(例如,不是
基本类型(如整数,而不是数组或列表等集合类型)
可以从JSON对象反序列化的。JsonObjectAttribute也可以是
添加到类型以强制其从JSON对象反序列化。
路径“response.result.Notes.row.no”,第1行,位置44。
在Json.Net中,有没有一种方法可以处理这个问题,它有一些属性,并且希望不必编写转换器?这个方法的灵感来源于一个类似的问题
public class ZohoDataMultiRowJson
{
[JsonConverter(typeof(ArrayOrObjectConverter<ZohoDataRowJson>))]
public List<ZohoDataRowJson> Row { get; set; }
}
public class ArrayOrObjectConverter<T> : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
return serializer.Deserialize<List<T>>(reader);
}
else if (reader.TokenType == JsonToken.StartObject)
{
return new List<T>
{
(T) serializer.Deserialize<T>(reader)
};
}
else
{
throw new NotSupportedException("Unexpected JSON to deserialize");
}
}
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
}
公共类ZohoDataMultiRowJson
{
[JsonConverter(类型(ArrayOrObjectConverter))]
公共列表行{get;set;}
}
公共类ArrayOrObjectConverter:JsonConverter
{
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotImplementedException();
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
if(reader.TokenType==JsonToken.StartArray)
{
返回序列化程序。反序列化(读取器);
}
else if(reader.TokenType==JsonToken.StartObject)
{
返回新列表
{
(T) 序列化程序。反序列化(读取器)
};
}
其他的
{
抛出新的NotSupportedException(“要反序列化的意外JSON”);
}
}
公共覆盖布尔CanConvert(类型objectType)
{
抛出新的NotImplementedException();
}
}
感谢@L.B的链接和链接问题的答案。ReadJson方法reader.ValueType中的另一个类似问题@L.B.始终为空。在本例中,我必须使用reader.TokenType,即StartArray或StartObject。此外,在这两种情况下,反序列化将继续进行。我想发布一个答案,因为它与两个链接的答案没有什么不同。我还想说出供应商的名字,这样可以帮助将来的用户遇到同样的问题。我重新打开了这个问题…谢谢@L.B。添加了答案。让答案更通用,而不仅仅是针对ZohoDataRowJson,怎么样?那样就完美了。顺便说一句,a+1有意义。更新。谢谢你的+1。