:: Не фоксом единым
JsonConvert.DeserializeObject
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
На www.newtonsoft.com есть пример "Deserialize with CustomCreationConverter". По шагам:

1. Открываю VS
2. Создаю консольный проект Core 3.1
3. Добавляю NuGet пакет Newtonsoft.Json
4. Меняю Program.cs на:


Запускаю, всё работает. Затем, немного меняю программу - добавляю класс

public class Department
{
public List<Person> Employees;
}

Как нужно изменить PersonConverter, что бы было можно десериализовать Department?



Исправлено 7 раз(а). Последнее : S-type, 15.02.22 20:04
Ratings: 0 negative/0 positive
Re: JsonConvert.DeserializeObject
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
Если задачу чуть упростить - считаем, что в Department может быть только один человек, то получается так:


А вот с List<Person> Employees - загвоздка.



Исправлено 2 раз(а). Последнее : S-type, 15.02.22 20:32
Ratings: 0 negative/0 positive
Re: JsonConvert.DeserializeObject
S-type
Автор

Сообщений: 2969
Дата регистрации: 24.04.2004
В итоге получилось вот так:


Теперь всё работает. Но, почему IEnumerable<Person>? Загадка...
Ratings: 0 negative/0 positive
Re: JsonConvert.DeserializeObject
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Слишком много всего понамешано

Начнём с того, что конвертер DepartmentsConverter вообще не нужен. Вполне достаточно конвертера PersonConverter, который делает немного странное - всегда создаёт экземпляры производного типа когда десериализатору на самом деле требуется базовый. И всё заработает с List<Person> - ну в той "постановке задачи" которую ты сделал.

Почему в 3-м примере тебе потребовался IEnumerable<T> - потому что он IEnumerable<out T> - ковариантный обобщённый интерфейс - ковариантность позволяет делать присваивание в IEnumerable<Base> объекта имеющего тип IEnumerable<Derived> (наподобии того как в Base можно присвоить экземпляр Derived). List<T> является инвариантным обобщённым типом, и не позволяет в List<Base> присвоить экземпляр List<Derived>. Ну а уж где именно ты пытался в Xxx<Base> явно записать экземпляр Xxx<Derived> оно видно Только этого не требуется на самом деле - для того чтобы в List<Base> добавить элемент с типом Derived вовсе не требуется сам лист делать типа List<Derived> (при том что это и невозможно).

Вообще это всё выглядит надуманным, т.к. если у тебя есть нечто типа Base, то и работать нужно с этим именно как с Base, а не преобразовывать тип к Derived, при том отлавливая ошибки такового преобразования. Прямое преобразование типа вообще вызовет исключение InvalidCastException, обычно используют оператор as c проверкой что после преобразования не получили null, ну или в современных версиях языка "Declaration and type patterns" - конструкцию вида
if (person is Employee employee)
{
Console.WriteLine(employee.JobTitle);
}
Но всё же в данном случае я не вижу смысла определять в модели тип как Person, явно предполагая хранить там всегда Employee (собственно говоря, это и делает конвертер). При том что на самом деле не произойдёт никакой трагедии, если в исходном json не будет каких-то данных для некоторых employee и они после десериализации будут иметь значения лишь в "базовых" свойствах.

Возможно стоит ознакомиться с библиотекой AutoMapper, и не пытаться одни и те же типы (и, соответственно, объекты) использовать на всех шагах процесса обработки - от десериализации из json (над структурой/наполнением которого зачастую у тебя нет контроля) до передачи в базу данных или в слой отображения. Порой эффективнее определять разные типы (пусть и с одинаковым/пересекающимся подмножеством свойств) для разных целей - десериализовать из базы/файла/ответа стороннего сервера, использовать в каких-то расчётах, сформировать "выходные данные" которые, в свою очередь, передать другим сервисам или в слой UI.

А возможно стоит посмотреть на опцию TypeNameHandling (возможно вкупе с SerializationBinder, чтобы не писать полные имена типов или проводить какую-то свою "конвертацию имён") - и банально включить в json дискриминаторы типов
'$type': 'ConsoleApp2.Program+Employee, ConsoleApp2'
. В результате автоматом получать объекты любого подтипа в иерархии наследования (в т.ч. и внутри List).

------------------
WBR, Igor
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 7 tata  (Гостей: 6)

© 2000-2024 Fox Club 
Яндекс.Метрика