IEnumerable的Json.Net序列化与TypeNameHandling = auto

Dav*_*rdi 8 c# json.net

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

所以我期待以下课程:

public class MyClass
{
    public IEnumerable<string> Values { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

被序列化为:

{
    "Values": []
}
Run Code Online (Sandbox Code Playgroud)

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

{
    "Values": {
        "$type": "System.String[], mscorlib",
        "$values": []
    }
}
Run Code Online (Sandbox Code Playgroud)

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

这是一个错误或我错过了什么?

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

    [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; }
    }
Run Code Online (Sandbox Code Playgroud)

我正在使用Newtonsoft 7.0.1.

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

    [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; }
    }
Run Code Online (Sandbox Code Playgroud)

这是结果:

{
    "Values1": {
        "$type": "System.String[], mscorlib",
        "$values": []
    },
    "Values2": [],
    "Values3": {
        "$type": "System.String[], mscorlib",
        "$values": []
    },
    "Values4": [],
    "Values5": []
}
Run Code Online (Sandbox Code Playgroud)

我再次理解为什么根据组合得到不同的结果.

Mei*_*hes 7

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

通过使用List<string>实例:

var myEvent = new MyClass
{
    Values = new List<string>(),
};
Run Code Online (Sandbox Code Playgroud)

和:

public class MyClass
{
   public IEnumerable<string> Values { get; set; }
}    
Run Code Online (Sandbox Code Playgroud)

结果(序列化时):

{"Values":["hello"]}
Run Code Online (Sandbox Code Playgroud)

另外,如果您使用显式可构造类型或使用默认 List,那么 Json.Net 将使用它并省略$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
Run Code Online (Sandbox Code Playgroud)