使用 Json.net 反序列化 JSON 对象数组
Posted
技术标签:
【中文标题】使用 Json.net 反序列化 JSON 对象数组【英文标题】:Deserializing JSON Object Array with Json.net 【发布时间】:2013-08-14 01:57:09 【问题描述】:我正在尝试使用一个 API,该 API 使用以下示例结构来返回其返回的 json
[
"customer":
"first_name":"Test",
"last_name":"Account",
"email":"test1@example.com",
"organization":"",
"reference":null,
"id":3545134,
"created_at":"2013-08-06T15:51:15-04:00",
"updated_at":"2013-08-06T15:51:15-04:00",
"address":"",
"address_2":"",
"city":"",
"state":"",
"zip":"",
"country":"",
"phone":""
,
"customer":
"first_name":"Test",
"last_name":"Account2",
"email":"test2@example.com",
"organization":"",
"reference":null,
"id":3570462,
"created_at":"2013-08-12T11:54:58-04:00",
"updated_at":"2013-08-12T11:54:58-04:00",
"address":"",
"address_2":"",
"city":"",
"state":"",
"zip":"",
"country":"",
"phone":""
]
JSON.net 可以很好地处理类似以下结构的东西
"customer":
["field1" : "value", etc...],
["field1" : "value", etc...],
但我不知道如何让它对提供的结构感到满意。
使用默认的 JsonConvert.DeserializeObject(content) 可以得到正确数量的客户,但所有数据均为空。
对 CustomerList(如下)执行操作会导致“无法反序列化当前 JSON 数组”异常
public class CustomerList
public List<Customer> customer get; set;
想法?
【问题讨论】:
这能回答你的问题吗? Deserialize JSON with C# 【参考方案1】:您可以创建一个新模型来反序列化您的 JSON CustomerJson
:
public class CustomerJson
[JsonProperty("customer")]
public Customer Customer get; set;
public class Customer
[JsonProperty("first_name")]
public string Firstname get; set;
[JsonProperty("last_name")]
public string Lastname get; set;
...
您可以轻松地反序列化您的 JSON:
JsonConvert.DeserializeObject<List<CustomerJson>>(json);
文档:Serializing and Deserializing JSON
【讨论】:
JsonConvert.DeserializeObject>(json);非常适合字符串输入。DeserializeObject()
在运行 ARM 的 android 手机上运行缓慢。对于这种情况有更好的解决方案吗?
尝试使用 JObject JObject.Parse(json);
进行导航【参考方案2】:
对于那些不想创建任何模型的人,使用以下代码:
var result = JsonConvert.DeserializeObject<
List<Dictionary<string,
Dictionary<string, string>>>>(content);
注意:这不适用于 您的 JSON 字符串。这不是任何 JSON 结构的通用解决方案。
【讨论】:
【参考方案3】:使用接受的答案,您必须使用Customers[i].customer
访问每条记录,并且您需要一个额外的CustomerJson
类,这有点烦人。如果您不想这样做,可以使用以下方法:
public class CustomerList
[JsonConverter(typeof(MyListConverter))]
public List<Customer> customer get; set;
请注意,我使用的是List<>
,而不是数组。现在创建以下类:
class MyListConverter : JsonConverter
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
var token = JToken.Load(reader);
var list = Activator.CreateInstance(objectType) as System.Collections.IList;
var itemType = objectType.GenericTypeArguments[0];
foreach (var child in token.Values())
var childToken = child.Children().First();
var newObject = Activator.CreateInstance(itemType);
serializer.Populate(childToken.CreateReader(), newObject);
list.Add(newObject);
return list;
public override bool CanConvert(Type objectType)
return objectType.IsGenericType && (objectType.GetGenericTypeDefinition() == typeof(List<>));
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();
【讨论】:
【参考方案4】:对上述内容稍作修改。我验证的 Json 格式是
mycollection:[
property0:value,
property1:value,
,
property0:value,
property1:value,
]
使用 AlexDev 的响应,我这样做了循环每个孩子,从中创建阅读器
public partial class myModel
public static List<myModel> FromJson(string json) => JsonConvert.DeserializeObject<myModelList>(json, Converter.Settings).model;
public class myModelList
[JsonConverter(typeof(myModelConverter))]
public List<myModel> model get; set;
class myModelConverter : JsonConverter
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
var token = JToken.Load(reader);
var list = Activator.CreateInstance(objectType) as System.Collections.IList;
var itemType = objectType.GenericTypeArguments[0];
foreach (var child in token.Children()) //mod here
var newObject = Activator.CreateInstance(itemType);
serializer.Populate(child.CreateReader(), newObject); //mod here
list.Add(newObject);
return list;
public override bool CanConvert(Type objectType)
return objectType.IsGenericType && (objectType.GetGenericTypeDefinition() == typeof(List<>));
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();
【讨论】:
【参考方案5】:从JC_VA进一步修改,取他所有的,把MyModelConverter替换成...
public class MyModelConverter : JsonConverter
//objectType is the type as specified for List<myModel> (i.e. myModel)
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
var token = JToken.Load(reader); //json from myModelList > model
var list = Activator.CreateInstance(objectType) as System.Collections.IList; // new list to return
var itemType = objectType.GenericTypeArguments[0]; // type of the list (myModel)
if (token.Type.ToString() == "Object") //Object
var child = token.Children();
var newObject = Activator.CreateInstance(itemType);
serializer.Populate(token.CreateReader(), newObject);
list.Add(newObject);
else //Array
foreach (var child in token.Children())
var newObject = Activator.CreateInstance(itemType);
serializer.Populate(child.CreateReader(), newObject);
list.Add(newObject);
return list;
public override bool CanConvert(Type objectType)
return objectType.IsGenericType && (objectType.GetGenericTypeDefinition() == typeof(List<>));
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();
这应该适用于 json
myModelList
model: [ ... object ... ]
或
myModelList
model: ... object ...
它们最终都会像被解析一样被解析
myModelList
model: [ ... object ... ]
【讨论】:
以上是关于使用 Json.net 反序列化 JSON 对象数组的主要内容,如果未能解决你的问题,请参考以下文章
使用 DataContractSerializer 发送反序列化的 Json.net 对象时出错
使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON.net 的json的序列化与反序列化