Использование Json.Net для анализа двух семантически идентичных документов иерархии и сбой
У меня есть два документа JSON, которые представляют одинаковую иерархическую структуру и содержание. Единственное различие, которое я вижу между этими двумя документами, состоит в том, что порядок пар ключ-значение различен. Один документ анализируется, как я ожидаю, а другой нет.
Я использую "Сохранение ссылок", поэтому узел должен ссылаться на своего родителя. (Переменная "ierarchyTwoNode"в тесте - это документ, для которого не установлено свойство 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"
}
}
Может ли кто-нибудь дать мне представление о том, что происходит?
2 ответа
Может ли кто-нибудь дать мне представление о том, что происходит?
По сути, происходит то, что в одной из строк JSON ваши свойства метаданных размещаются после первого фактического свойства.
все $xxx
свойства являются метаданными и должны быть размещены в начале объекта / подобъекта.
Причина этого ограничения заключается в следующем:
если мы посмотрим на внутреннюю часть JSON.Net, при выполнении поиска метаданных мы увидим, что как только мы читаем свойство, которое не является метаданными, мы прекращаем поиск метаданных.
Я могу только предположить, что он предназначен для оптимизации вычислений и памяти, если файл JSON будет очень большим.
Чтобы ваш код работал, просто поместите все свойства, начинающиеся с $
в начале объекта, и он должен работать как шарм.
Как правильно вывел @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);