使用TypeNameHandling = auto的IEnumerable的Json.Net序列化 [英] Json.Net serialization of IEnumerable with TypeNameHandling=auto
问题描述
根据 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的默认自动行为是在反序列化为IEnumerable
或IList
字段时,创建一个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屋!