2016-06-01 8 views
0

(Использование Newtonsoft Json.NET)Десериализация с Наследование Newtonsoft JSON.NET не работает должным образом

Привет У меня есть проблема, когда десериализации список событий, где событие является базовым типом и, например, ResourceEvent - это подкласс. Если я просто выполняю сериализацию, а затем десериализую, все работает нормально, а список содержит ResourceEvents. Однако я храню те, которые используют EF7, в столбец jsonb в postgres.

Когда я получаю полезную нагрузку JSON из postgres, он переупорядочивает (но JSON legal) свойства. Когда я пытаюсь десериализовать с помощью Newtonsoft JSON.net, он дает мне список с базовыми типами Event, а не подкласса ResourceEvent.

Я добавил два сильно разборных примера, где различия заключаются в том, что свойство «Тип» находится в разных местах. В других классах также были упорядочены другие свойства. У меня нет комментариев по классам вообще.

Эта полезная нагрузка успешно deseralizes:

json 
{ 
    "$type": "System.Collections.Generic.List`1[[Event, Tests]], mscorlib", 
    "$values": [ 
     { 
      "$type": "ResourceConfigurationEvent, Tests", 
      /* Properties */ 
      "Resources": { 
       /* Properties */     
      }, 
      "Type": 1    
     } 
    ] 
} 

Эта полезная нагрузка безуспешно десериализует:

json 
{ 
    "$type": "System.Collections.Generic.List`1[[Event, Tests]], mscorlib", 
    "$values": [ 
     { 
      "Type": 1,    
      "$type": "ResourceConfigurationEvent, Tests", 
      /* Properties */ 
      "Resources": { 
       /* Properties */     
      }, 
     } 
    ] 
} 
+2

Пожалуйста, прочтите [ask] и предоставьте [mcve], сфокусируйтесь на ** минимальном **. – CodeCaster

+0

Прокрутить ... прокрутить ... прокрутить ... прокрутить ... прокрутить ... прокрутить ... нах, чтобы многое прочитать. – Reniuz

+0

Можете ли вы предоставить определение класса, предложите не дезацинировать словарь, но что-то вроде этого [IgnoreDataMember] общедоступный словарь >(); [DataMember (Name = "name you want")] public IEnumerable ObjectToStore –

ответ

2

Json.Net обычно ожидает, что $type метаданные, чтобы быть первым свойством каждого объекта для лучшей эффективности в десериализации. Если $type не появляется первым, Json.Net предполагает, что его там нет. Вот почему вы получаете разные результаты, когда свойства переупорядочиваются.

К счастью, Json.Net предоставляет настройку MetadataPropertyHandling, позволяющую ей справиться с этой ситуацией. Если вы установите MetadataPropertyHandling на номер , он должен решить вашу проблему. Обратите внимание, что это повлияет на производительность.

Ниже приведена документация code sample.

string json = @"{ 
    'Name': 'James', 
    'Password': 'Password1', 
    '$type': 'MyNamespace.User, MyAssembly' 
}"; 

object o = JsonConvert.DeserializeObject(json, new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.All, 
    // $type no longer needs to be first 
    MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead 
}); 

User u = (User)o; 

Console.WriteLine(u.Name); 
// James 
+0

Спасибо! Работает как шарм! Я проверю с ребятами postgres, если они могут сохранить порядок в столбце «jsonb». Еще раз спасибо за быстрый ответ! :) –

+0

Рад, что я мог помочь. –

+0

Вы настоящий спасатель! –

Смежные вопросы