【发布时间】:2017-01-15 04:14:48
【问题描述】:
我和我的团队在 C# 中使用 JSON.NET 反序列化时遇到了一个奇怪的行为。
我们有一个带有 IOrderedEnumerable<long> 的简单 ViewModel:
public class TestClass
{
public IOrderedEnumerable<long> orderedDatas { get; set; }
public string Name { get; set; }
public TestClass(string name)
{
this.Name = name;
this.orderedDatas = new List<long>().OrderBy(p => p);
}
}
然后,我们只想将此视图模型 POST/PUT 到 API 控制器中
[HttpPost]
public IHttpActionResult Post([FromBody]TestClass test)
{
return Ok(test);
}
使用如下所示的 json 调用此 API:
{
Name: "tiit",
"orderedDatas": [
2,
3,
4
],
}
通过这个调用,我们看到构造函数没有被调用(这可以通过它不是默认构造函数来解释)。但奇怪的是,如果我们把集合的类型改成IEnumerable或者IList,构造函数就正确调用了。
如果我们将TestClass 的构造函数更改为默认构造函数:
public class TestClass
{
public IOrderedEnumerable<long> orderedDatas { get; set; }
public string Name { get; set; }
public TestClass()
{
this.Name = "default";
this.orderedDatas = new List<long>().OrderBy(i => i);
}
}
控制器检索的对象不会为空。
如果我们将集合的类型更改为IEnumerable,并为构造函数保留一个参数(公共TestClass(string name)),它也可以工作。
另外一个奇怪的是控制器中的对象测试是“null”。不仅orderedDatas为null,整个对象也是。
如果我们在类上添加一个属性[JsonObject],并在属性orderedData 上添加一个[JsonIgnore],它就可以工作。
目前,我们将对象更改为一个简单的 List 并且它工作正常,但我们想知道为什么 JSON 反序列化的行为会根据集合的类型而有所不同。
如果我们直接使用 JsonConvert.Deserialize :
var json = "{ Name: 'tiit', 'orderedDatas': [2,3,4,332232] }";
var result = JsonConvert.DeserializeObject<TestClass>(json);
我们可以看到实际的异常:
无法创建和填充列表类型 System.Linq.IOrderedEnumerable`1[System.Int64]。路径 'orderedDatas', 第 1 行,位置 33。
感谢任何想法/帮助。
谢谢!
** 编辑:感谢您的回答。有一件事我一直觉得很奇怪(我用粗体表示),如果你有任何想法来解释这种行为,请告诉我**
【问题讨论】:
-
IOrderedEnumerable只是一个接口。列表和数组是 not 有序的,因此它们不实现该接口。如果您想使用特定的集合类型而不是数组,您可能应该使用自定义转换器来创建您想要的类型(也许是 SortedList?)
标签: c# json serialization json.net json-deserialization