Newtonsoft反序列化从Collection <item>扩展的对象

时间:2016-07-29 18:26:20

标签: c# json.net

我试图使用NewtonSoft.Json反序列化程序,但我不知道我尝试做的事情是否可行,因此我所见过的每个集合示例都是像这样:

public class ItemRecords 
{
     public List<ItemRecords> Items { get; set; }
     ...
}

我想要的是看起来像下面所解释的......

我有这两个类:

public class ItemRecords : Collection<ItemRecord>  
{  
    [JsonProperty("property1")]
    public int Property1 { get; set; }  

    [JsonProperty("property2")]
    public int Property2 { get; set; }  
}

public class ItemRecord
{   
    [JsonProperty("id")]
    public int Id { get; set; }

    [JsonProperty("item_prop1")]
    public string ItemProp1 { get; set; }
    ...
}

我从我的api那里得到了这个json:

{  
    property1: 25,
    property2: 27,
    item_record: [
       {
           id: 241,
           item_prop1: "0.132",
           item_prop2: "78787",
           ...
       },
       {
           id: 242
           item_prop1: "1212",
           item_prop2: "3333",
           ...
       }
       ...
    ]
}

ItemRecords是ItemRecord的集合 我尝试将JsonArray属性添加到ItemRecords类,如下所示:

[JsonArray(ItemConverterType = typeof(ItemRecord))]
public class ItemRecords : Collection<ItemRecord> { ... }

以下是执行请求的方法:

private static async Task<T> MakeRequest<T>(string urlRequest)
{
    try
    {
        HttpWebRequest request = WebRequest.Create(urlRequest) as HttpWebRequest;

        using (WebResponse response = await request.GetResponseAsync())
        {
            using (Stream stream = response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(stream);

                string line = string.Empty;
                StringBuilder sb = new StringBuilder();

                while ((line = reader.ReadLine()) != null)
                {
                    sb.Append(line);
                }

                T objectDeserialized = JsonConvert.DeserializeObject<T>(sb.ToString());                        

                return objectDeserialized;
            }
        }
    }
    catch (Exception ex)
    {
        return default(T);
    }
}

调用此方法如下所示:

...
return await MakeRequest<ItemRecords>(request);

我真的不知道还能做什么...... 任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:1)

只需将List<ItemRecord> Records属性添加到课程ItemRecords

public class ItemRecords
{
    [JsonProperty("property1")]
    public int Property1 { get; set; }  

    [JsonProperty("property2")]
    public int Property2 { get; set; }  

    [JsonProperty("item_record")]
    public List<ItemRecord> Records { get; set; } 
}

答案 1 :(得分:1)

您的基本困难是JSON standard有两种类型的容器:

  • 对象,它是一组无序的名称/值对。对象以{(左大括号)开头,以}(右大括号)结束。 Json.NET默认将字典和不可枚举的POCOS映射到对象,使用反射将c#属性映射到JSON属性。

    在您从API返回的JSON中,最外面的容器是一个对象。

  • 数组,它是有序的值集合。数组以[(左括号)开头,以](右括号)结尾。值以,(逗号)分隔。 Json.NET默认将非字典枚举映射到数组,将每个集合项序列化为数组条目。

    在您从API返回的JSON中,item_record属性的值是一个数组。

作为具有属性的集合,您的ItemRecords无法自动映射到这些构造中的任何一个而不会丢失数据。由于Json.NET默认将集合序列化为数组,因此您需要通过应用[JsonObject]属性手动通知它将您的类型序列化为对象。然后,引入合成的item_record属性来序列化和反序列化集合项。由于您继承自Collection<T>,因此可以使用Collection<T>.Items来实现此目的:

[JsonObject(MemberSerialization.OptIn)]
public class ItemRecords : Collection<ItemRecord>  
{  
    [JsonProperty("property1")]
    public int Property1 { get; set; }  

    [JsonProperty("property2")]
    public int Property2 { get; set; }  

    [JsonProperty("item_record")]
    IList<ItemRecord> ItemRecordList
    {
        get 
        {
            return Items;
        }
    }
}

使用MemberSerialization.OptIn可以防止序列化Count等基类属性。

示例fiddle

顺便说一下,我不特别推荐这种设计,因为它可能会导致其他序列化程序出现问题。例如,XmlSerializer永远不会序列化集合属性;请参阅herehere。另请参阅Why not inherit from List?

答案 2 :(得分:0)

看起来您可以拥有动态数量的属性和项属性结果,例如:

{  
    property1: 25,
    property2: 27,
    property3: 30,
    item_record: [
       {
           id: 241,
           item_prop1: "0.132",
           item_prop2: "78787"
       },
       {
           id: 242
           item_prop1: "1212",
           item_prop2: "3333",
           item_prop3: "3333",
           item_prop4: "3333",
       }
    ] }

如果是这种情况,我认为最好的选择是将结构改为:

{
    properties:[
       25,
       27,
       30
    ],
    itemRecords:[
        {
            id: 27,
            itemProperties:[
                "321",
                "654",
                "564"
            ]
        },
        {
            id: 25,
            itemProperties:[
                "321",
                "654"
            ]
        },
    ]
}