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

问题描述 投票:0回答:7

我尝试使用一个 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 可以很好地处理类似以下结构的内容

{
    "customer": {
        ["field1" : "value", etc...],
        ["field1" : "value", etc...],
    }
}

但我不知道如何让它对所提供的结构感到满意。

使用默认的 JsonConvert.DeserializeObject(content) 会产生正确的 Customer 数量,但所有数据均为空。

对 CustomerList(如下)执行某些操作会导致“无法反序列化当前 JSON 数组”异常

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

想法?

c# json.net
7个回答
221
投票

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


49
投票

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

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

注意:这可能不适用于您的 JSON 字符串。这不是任何 JSON 结构的通用解决方案。它适用于问题中的 JSON 结构。对于你自己的JSON结构,你需要调整代码。

使用接受的答案,您必须使用

4
投票
访问每条记录,并且您需要一个额外的

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();
}

对上述内容稍作修改。我的 Json 格式,经过验证是 

2
投票
{ 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(); }

JC_VA 的进一步修改,取他已有的,并将 MyModelConverter 替换为...

0
投票
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 ... }] }

简单:创建两个类,一个用于客户,另一个用于数组对象。

0
投票

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

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



现在,您可以使用 System.Text.Json 和 JsonSerializer 类。要么

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.