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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 11:30:42  来源:igfitidea点击:

Deserializing JSON Object Array with Json.net

c#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

文档:序列化和反序列化 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 CustomerJsonclass, 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 ... }]
}