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

149

我正在尝试使用一个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)可以得到正确数量的 Customer,但所有数据都为 null。

将内容转换为 CustomerList(如下所示)会导致“无法反序列化当前的 JSON 数组”异常。

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

您有什么想法?


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

221

您可以创建一个新的模型来反序列化您的JSONCustomerJson

    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


2
JsonConvert.DeserializeObject<List<CustomerJson>>(json); 对于字符串输入完美运作。 - Markel Mairs
1
DeserializeObject() 在运行 ARM 的 Android 手机上速度较慢。有更好的解决方案吗? - tedi
1
尝试使用 JObject 进行导航,即 JObject.Parse(json); - Joffrey Kern

49

如果您不想创建任何模型,可以使用以下代码:

var result = JsonConvert.DeserializeObject<
  List<Dictionary<string, 
    Dictionary<string, string>>>>(content);
注意:这不适用于你的JSON字符串。这不是任何JSON结构的通用解决方案。

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


4
使用被接受的答案,您需要通过使用Customers[i].customer来访问每条记录,并且需要一个额外的CustomerJson类,这有些麻烦。如果您不想这样做,可以使用以下方法:
public class CustomerList
{
    [JsonConverter(typeof(MyListConverter))]
    public List<Customer> customer { get; set; }
}

请注意,我正在使用 List<>,而不是 Array。现在创建以下类:
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

现在,您可以使用System.Text.Json和JsonSerializer类。任何一个都可以。

CustomerList customers = JsonSerializer.Deserialize<CustomerList>(json);

或者

List<Customer> customers = JsonSerializer.Deserialize<List<Customer>>(json);

前者是您自己的POCO类,其中包含标量或数组属性的组合。后者用于反序列化特定的数组对象。


0

简单来说:创建两个类,一个用于客户,另一个用于数组对象。
JSON字符串如下:

{
  "fieldObjects": [
    {
      "Field1": "ValueField1_a",
      "Field2": "ValueField2_a"
    },
    {
      "Field1": "ValueField1_b",
      "Field2": "ValueField2_b"
    }
  ]
}

在 .net 中,您有一个名为 fieldObjects 的一级(父)类,它仅包含一个子类列表属性。 子类包含属性 Field1、Field2 等。
最后,使用父类对 Json 字符串进行 DeserializeObject,而不使用列表...
就这些。

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 ... }]
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接