使用TypeNameHandling = auto的IEnumerable的Json.Net序列化 [英] Json.Net serialization of IEnumerable with TypeNameHandling=auto

查看:41
本文介绍了使用TypeNameHandling = auto的IEnumerable的Json.Net序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 Json.Net文档,所有IEnumerable类型均应被序列化为json数组.

According to Json.Net documentation all IEnumerable types should be serialized as json array.

所以我希望有以下课程:

So I expect the following class:

public class MyClass
{
    public IEnumerable<string> Values { get; set; }
}

序列化为:

{
    "Values": []
}

问题是,当我使用TypeNameHandling=Auto时,我得到了:

The problem is that when I use TypeNameHandling=Auto I get:

{
    "Values": {
        "$type": "System.String[], mscorlib",
        "$values": []
    }
}

我需要TypeNameHandling=Auto的其他属性,但我希望IEnumerable使用默认的序列化.其他类型(例如IList)可以按预期工作.

I need TypeNameHandling=Auto for other properties but I expect IEnumerable to use the default serialization. Other types (IList for example) works as expected.

这是一个错误,还是我错过了一些东西?

It is a bug or I missing something?

这里是完整的代码来重现该问题:

Here the full code to reproduce the problem:

    [Test]
    public void Newtonsoft_serialize_list_and_enumerable()
    {
        var target = new Newtonsoft.Json.JsonSerializer
        {
            TypeNameHandling = TypeNameHandling.Auto
        };

        var myEvent = new MyClass
        {
            Values = new string[0]
        };

        var builder = new StringWriter();
        target.Serialize(builder, myEvent);
        var json = JObject.Parse(builder.ToString());

        Assert.AreEqual(JTokenType.Array, json["Values"].Type);
    }

    public class MyClass
    {
        public IEnumerable<string> Values { get; set; }
    }

我正在使用Newtonsoft 7.0.1.

I'm using Newtonsoft 7.0.1.

更新: 这里是使用更多类型的另一个测试:

UPDATE: Here another test using more types:

    [Test]
    public void Newtonsoft_serialize_list_and_enumerable()
    {
        var target = new Newtonsoft.Json.JsonSerializer
        {
            TypeNameHandling = TypeNameHandling.Auto
        };

        var myEvent = new MyClass
        {
            Values1 = new string[0],
            Values2 = new List<string>(),
            Values3 = new string[0],
            Values4 = new List<string>(),
            Values5 = new string[0]
        };

        var builder = new StringWriter();
        target.Serialize(builder, myEvent);
        var json = builder.ToString();
    }

    public class MyClass
    {
        public IEnumerable<string> Values1 { get; set; }
        public IEnumerable<string> Values2 { get; set; }
        public IList<string> Values3 { get; set; }
        public IList<string> Values4 { get; set; }
        public string[] Values5 { get; set; }
    }

这是结果:

{
    "Values1": {
        "$type": "System.String[], mscorlib",
        "$values": []
    },
    "Values2": [],
    "Values3": {
        "$type": "System.String[], mscorlib",
        "$values": []
    },
    "Values4": [],
    "Values5": []
}

再次,我不明白为什么我会因组合而得到不同的结果.

Again I don't understand why I get different results depending on the combination.

推荐答案

Json.Net的默认自动行为是在反序列化为IEnumerableIList字段时,创建一个List实例.如果分配一个Array实例,那么将对象还原到其原始实例状态的唯一方法是让Json.Net添加$type元数据,这就是您所看到的. 即有很多方法可以反序列化为IEnumerable字段.

The default automatic behaviour of Json.Net, when deserializing into an IEnumerable or IList field, is to create a List instance. If you assign an Array instance, then the only way to restore your object to it original instance state is for Json.Net to add the $type meta data, which is what you are seeing. i.e. there are many ways to deserialize into an IEnumerable field.

通过使用List<string>实例:

var myEvent = new MyClass
{
    Values = new List<string>(),
};

具有:

public class MyClass
{
   public IEnumerable<string> Values { get; set; }
}    

导致(序列化时):

{"Values":["hello"]}

此外,如果您使用显式的可构造类型或使用默认的List,则Json.Net将使用该类型并省略$type;否则,将使用$type.

Also, if you use an explicit constructable type or use the default List, then Json.Net will use that and omit $type;

例如:

string[] Values { get; set; } = new string[0]; // not needed
IEnumerable<string> Values { get; set; } = new string[0]; //$type needed
IEnumerable<string> Values { get; set; } = new Stack<string>(); //$type needed
IEnumerable<string> Values { get; set; } = new List<string>; // not needed
List<string> Values { get; set; } = new List<string>; // not needed

ObservableCollection<string> Values { get; set; } = 
    new ObservableCollection<string>(); // not needed

这篇关于使用TypeNameHandling = auto的IEnumerable的Json.Net序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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