我有两个JSON文档,它们代表相同的层次结构和内容。我可以看到这两个文档之间的唯一区别是键值对的顺序不同。一个文档按我的预期解析,而另一个则不然。
我正在使用"保留引用处理",因此节点应引用其父节点。(测试中的变量"hierarchyTwoNode"是未设置其 Parent 属性的文档(。我包括了一个测试(可以在这里找到(来证明这一点。 以下是工作 JSON 的简化版本:
{
"Root": {
"$id": "1",
"Id": "1472459628771017730",
"Type": "cras",
"Content": {
"Name": "lorem"
},
"Parent": null,
"Children": [
{
"$id": "2",
"Id": "1472459628812960771",
"Type": "morbi",
"Content": {
"Name": "ipsum dolor"
},
"Parent": {
"$ref": "1"
}
}
]
}
}
还有失败的 JSON:
{
"Root": {
"Parent": null,
"$id": "1",
"Children": [
{
"Parent": {
"$ref": "1"
},
"$id": "2",
"Content": {
"Name": "ipsum dolor"
},
"Type": "morbi",
"Id": "1472459628812960771"
}
],
"Content": {
"Name": "lorem"
},
"Type": "cras",
"Id": "1472459628771017730"
}
}
有人可以告诉我正在发生的事情吗?
有人可以告诉我正在发生的事情吗?
本质上,正在发生的事情是,在其中一个 JSON 字符串上,元数据属性放置在第一个实际属性之后。
所有$xxx
属性都是元数据,必须放在对象/子对象的开头。
此限制的原因如下:
如果我们查看 JSON.Net 的内部结构,在执行元数据查找时,我们可以看到,一旦我们读取不是元数据的属性,我们就会停止元数据查找。
我只能做出公平的假设,即如果 JSON 文件非常大,它用于计算和内存优化。
若要使代码正常工作,只需将$
开头的所有属性放在对象的开头,它应该像一个超级按钮一样工作。
正如Salvalai正确推断@Fabio的那样,Json.Net 通常希望任何元数据属性(如$id
或$type
(首先出现在每个对象中,以获得最佳的反序列化效率。如果元数据没有首先出现,则 Json.Net 假定它不存在。这就是为什么在重新排序属性时会得到不同的结果。
幸运的是,Json.Net 提供了一个MetadataPropertyHandling
设置,以允许它处理这种情况。 如果将MetadataPropertyHandling
设置为ReadAhead
它应该可以解决您的问题。 请注意,如果 JSON 很大,这可能会对性能产生影响。
JsonSerializerSettings settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead
};
var hierarchyOne = JsonConvert.DeserializeObject<Hierarchy>(HierarchyOne, settings);
var hierarchyTwo = JsonConvert.DeserializeObject<Hierarchy>(HierarchyTwo, settings);