C# 使用 Json.net 反序列化 JSON 对象数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18192357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Deserializing JSON Object Array with Json.net
提问by Shawn C.
I am attempt to use an API that use the follow example structure for their returned json
我试图使用一个 API,该 API 使用以下示例结构作为返回的 json
[
{
"customer":{
"first_name":"Test",
"last_name":"Account",
"email":"[email protected]",
"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":"[email protected]",
"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 would work great with something like the following structure
JSON.net 可以很好地使用以下结构
{
"customer": {
["field1" : "value", etc...],
["field1" : "value", etc...],
}
}
But I can not figure out how to get it to be happy with the provided structure.
但我不知道如何让它对提供的结构感到满意。
Using the default JsonConvert.DeserializeObject(content) results the correct number of Customer but all of the data is null.
使用默认的 JsonConvert.DeserializeObject(content) 会得到正确数量的 Customer,但所有数据都为空。
Doing something a CustomerList (below) results in a "Cannot deserialize the current JSON array" exception
对 CustomerList(如下)执行某些操作会导致“无法反序列化当前 JSON 数组”异常
public class CustomerList
{
public List<Customer> customer { get; set; }
}
Thoughts?
想法?
采纳答案by Joffrey Kern
You can create a new model to Deserialize your Json CustomerJson
:
您可以创建一个新模型来反序列化您的 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; }
...
}
And you can deserialize your json easily :
您可以轻松反序列化您的 json:
JsonConvert.DeserializeObject<List<CustomerJson>>(json);
Hope it helps !
希望能帮助到你 !
Documentation: Serializing and Deserializing JSON
回答by Tyler Long
For those who don't want to create any models, use the following code:
对于那些不想创建任何模型的人,请使用以下代码:
var result = JsonConvert.DeserializeObject<
List<Dictionary<string,
Dictionary<string, string>>>>(content);
Note: This doesn't work for yourJSON string. This is nota general solution for any JSON structure.
注意:这不适用于您的JSON 字符串。这不是任何 JSON 结构的通用解决方案。
回答by AlexDev
Using the accepted answer you have to access each record by using Customers[i].customer
, and you need an extra CustomerJson
class, which is a little annoying. If you don't want to do that, you can use the following:
使用接受的答案,您必须使用 访问每条记录Customers[i].customer
,并且您需要一个额外的CustomerJson
类,这有点烦人。如果您不想这样做,可以使用以下方法:
public class CustomerList
{
[JsonConverter(typeof(MyListConverter))]
public List<Customer> customer { get; set; }
}
Note that I'm using a List<>
, not an Array. Now create the following class:
请注意,我使用的是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();
}
回答by JC_VA
Slight modification to what was stated above. My Json format, which validates was
对上述内容略作修改。我的 Json 格式,它验证是
{
mycollection:{[
{
property0:value,
property1:value,
},
{
property0:value,
property1:value,
}
]
}
}
Using AlexDev's response, I did this Looping each child, creating reader from it
使用 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();
}
回答by andmar8
Further modification from JC_VA, take what he has, and replace the MyModelConverter with...
从 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();
}
This should work for json that is either
这应该适用于 json 要么
myModelList{
model: [{ ... object ... }]
}
or
或者
myModelList{
model: { ... object ... }
}
they will both end up being parsed as if they were
他们最终都会被解析,好像他们是
myModelList{
model: [{ ... object ... }]
}