我有两个JSON文档,它们代表相同的层次结构和内容。我可以在两个文档之间看到的唯一区别是键值对的排序是不同的。一个文档按照我的预期进行解析,而另一个文档则没有。
我正在使用“保留引用处理”,因此节点应引用其父节点。 (测试中的变量“hierarchyTwoNode”是未设置其Parent属性的文档)。我已经包含了一个测试(can be found here)来证明这一点。以下是工作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"
}
}
有人可以让我知道发生了什么吗?
答案 0 :(得分:2)
有人可以让我知道发生了什么吗?
基本上,正在发生的事情是,在其中一个JSON字符串上,您的元数据属性放在之后第一个实际属性。
所有$xxx
属性都是元数据,必须放在对象/子对象的开头。
此限制的原因如下:
JSON.Net的if we look at the internals,在执行元数据查找时,我们可以看到,只要我们读取不是元数据的属性,我们就会停止元数据查找。
如果JSON文件非常大,我只能公平地假设它是用于计算和内存优化的。
要使代码正常工作,只需在对象的开头放置以$
开头的所有属性,它就像魅力一样。
答案 1 :(得分:2)
正如@Fabio Salvalai正确推断的那样,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);