Newtonsoft反序列化从Collection< Item>扩展的对象. [英] Newtonsoft deserialize object that extends from Collection<Item>

查看:68
本文介绍了Newtonsoft反序列化从Collection< Item>扩展的对象.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用NewtonSoft.Json反序列化器,但是我不知道我想做的事情是否可行,请查看我所看到的每个收藏集示例:

I'm trying to use NewtonSoft.Json deserializer, but I don't know if what I'm trying to do is doable, cuase every example of collections that I've seen are like this:

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

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

And what I want is something that looks like as it's explained below...

我有这两节课:

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:

I get this json back from my api:

{  
    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类,如下所示:

ItemRecords is a collection of ItemRecord.
I tried by adding the JsonArray attribute to the ItemRecords class as follows:

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

对这个方法的调用如下:

And call to this method looks like this:

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

我真的不知道该怎么办. 任何帮助将不胜感激.

I don't really know what else to do.. Any help would be appreciated.

推荐答案

您的基本困难是 JSON标准有两种容器:

Your basic difficulty is that the JSON standard has two types of container:

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

  • The object which is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Json.NET maps dictionaries and non-enumerable POCOS to objects by default, using reflection to map c# properties to JSON properties.

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

In the JSON you are getting back from your API, the outermost container is an object.

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

The array which is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma). Json.NET maps non-dictionary enumerables to arrays by default, serializing each collection item as an array entry.

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

In the JSON you are getting back from your API, the value of the item_record property is an array.

作为具有属性的集合,ItemRecords不能在不丢失数据的情况下自动映射到这些结构中的任何一个.由于Json.NET默认将集合序列化为数组,因此您需要通过应用 Collection<T>.Items 为此:

As a collection with properties, your ItemRecords cannot be mapped to either of these constructs automatically without losing data. Since Json.NET serializes collections as arrays by default, you will need to manually inform it that your type is to be serialized as an object by applying the [JsonObject] attribute. Then, introduce a synthetic item_record property to serialize and deserialize the collection items. Since you are inheriting from Collection<T>, you can use Collection<T>.Items for this purpose:

[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之类的基类属性进行序列化.

Using MemberSerialization.OptIn prevents base class properties such as Count from being serialized.

示例小提琴.

顺便说一句,我不特别推荐这种设计,因为它可能导致其他串行器出现问题.例如,XmlSerializer永远不会序列化集合属性;请参见此处或<请在href ="https://stackoverflow.com/questions/34221481/how-to-serialize-an-icollectiont-that-also-has-read-write-properties-to-xml">此处.另请参见为什么不从List继承?.

As an aside, I don't particularly recommend this design, as it can cause problems with other serializers. For instance, XmlSerializer will never serialize collection properties; see here or here. See also Why not inherit from List?.

这篇关于Newtonsoft反序列化从Collection&lt; Item&gt;扩展的对象.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆