根据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)
我再次理解为什么根据组合得到不同的结果.
当反序列化为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)
| 归档时间: |
|
| 查看次数: |
5645 次 |
| 最近记录: |