根据 Json.Net documentation所有 IEnumerable
类型都应序列化为 json 数组。
所以我期待以下类(class):
public class MyClass
{
public IEnumerable<string> Values { get; set; }
}
被序列化为:
{
"Values": []
}
问题是,当我使用 TypeNameHandling=Auto
时,我得到:
{
"Values": {
"$type": "System.String[], mscorlib",
"$values": []
}
}
我需要 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; }
}
我正在使用 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; }
}
这是结果:
{
"Values1": {
"$type": "System.String[], mscorlib",
"$values": []
},
"Values2": [],
"Values3": {
"$type": "System.String[], mscorlib",
"$values": []
},
"Values4": [],
"Values5": []
}
我还是不明白为什么我会根据组合得到不同的结果。
最佳答案
当反序列化为 IEnumerable
时,Json.Net 的默认自动行为或 IList
字段,就是创建一个List
实例。如果您分配 Array
实例,那么将对象恢复到其原始实例状态的唯一方法是让 Json.Net 添加 $type
元数据,这就是您所看到的。 即有很多方法可以反序列化为 IEnumerable
字段。
通过使用 List<string>
实例:
var myEvent = new MyClass
{
Values = new List<string>(),
};
与:
public class MyClass
{
public IEnumerable<string> Values { get; set; }
}
结果(序列化时):
{"Values":["hello"]}
此外,如果您使用显式可构造类型或使用默认列表,则 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
关于c# - 带有 TypeNameHandling=auto 的 IEnumerable 的 Json.Net 序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34662966/