使用Json.net反序列化JSON对象数组


118

我尝试使用对以下返回的json使用以下示例结构的API

[
   {
      "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)可以得出正确数量的Customer,但所有数据均为null。

做一个CustomerList(如下)会导致“无法反序列化当前JSON数组”异常

public class CustomerList
{
    public List<Customer> customer { get; set; }
}

有什么想法吗?


这回答了你的问题了吗?使用C#反序列化JSON
GetFookedWeeb

Answers:


187

您可以创建一个新模型来反序列化您的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);

希望能帮助到你 !

文档:序列化和反序列化JSON


1
谢谢。在考虑问题。当您首先回答时,您的答案就被接受了。
Shawn C.

2
JsonConvert.DeserializeObject <列表<CustomerJson >>(json); 非常适合字符串输入。
Markel Mairs

DeserializeObject()在运行ARM的Android手机上运行缓慢。有什么更好的解决方案吗?
塔德伊

1
尝试使用JObject导航JObject.Parse(json);
Joffrey Kern

47

对于那些不想创建任何模型的人,请使用以下代码:

var result = JsonConvert.DeserializeObject<
  List<Dictionary<string, 
    Dictionary<string, string>>>>(content);

注意:这不适用于您的 JSON字符串。这不是任何JSON结构的通用解决方案。


10
这是一个糟糕的解决方案。相反,如果您不想创建模型,请使用var result = JsonConvert.DeserializeObject<Tuple<string, string, string>>(content);
a11smiles

1
@ a11smiles请解释为什么这是一个糟糕的解决方案。
泰勒·朗

2
首先,为不同类型的IEnumerable实现分配不必要的内存(与List <Tuple>相比为3)。其次,您的解决方案包含两个不同的键-每个字典1个。如果多个客户具有相同的名字会怎样?按键上没有区别。您的解决方案不考虑此冲突。
a11smiles

2
@ a11smiles每个客户都是单独的词典。因此,即使有多个具有相同名字的客户也不会有任何问题。
泰勒·朗

1
@ a11smiles我想知道为什么您认为var result = JsonConvert.DeserializeObject<Tuple<string, string, string>>(content);会工作。显然它不起作用
Tyler Long

1

使用已接受的答案,您必须使用来访问每个记录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();
}

1

对上述内容稍作修改。我的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();

}

0

从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 ... }]
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.