Как заполнить коллекцию IList с помощью Json.NET

#c# #json #json.net

#c# #json #json.net

Вопрос:

У нас есть такой User класс:

 public class User
{
    public string Name;
    public IList Roles;
}
  

и такой Role класс, как этот:

 public class Role
{
    public string Name;
}
  

Когда я сериализую, а затем десериализую User объект с помощью Json.NET Я получаю список JSON вместо Roles . Как я могу настроить Json.Как правильно десериализовать объект? User

Обновлено: пожалуйста, учтите, что изменение кода не является опцией, потому что это часть устаревшей системы, и многие системы зависят от этой библиотеки.

Ответ №1:

Вы должны указать параметр общего типа в своем списке, поэтому Json .NET понимает, что вам нужен список Role , например:

 public class User
{
    public string Name { get; set; }

    public IList<Role> Roles { get; set; }
}
  

Не забудьте добавить using System.Collections.Generic

Поскольку вы не указали для своего параметра общего типа IList , он фактически станет IList<object> тем, что, в свою очередь, создает Json .NET обрабатывает ее содержимое как JObject .

Из Json.СЕТЕВАЯ документация:

Свойства .NET для класса, которые не Указывают тип (т. Е. Они Просто object ), сериализуются как обычно. Когда нетипизированные свойства десериализуются, сериализатор не имеет возможности узнать, какой тип создавать (если не включена обработка имен типов и JSON содержит имена типов). Для этих нетипизированных свойств используется Json.NET serializer считывает JSON в LINQ для объектов JSON и присваивает им свойство. JObject будет создан для объектов JSON, JArray будет создан для массивов JSON, а JValue — для примитивных значений JSON.

РЕДАКТИРОВАТЬ: если у вас по какой-то причине нет возможности добавить аргументы универсального типа, есть другая альтернатива; установив TypeNameHandling значение либо Arrays или All (или, может быть, даже Auto ), Json .NET будет включать $type свойство (и $values свойство для массивов) в сериализованный JSON, чтобы сериализатор знал, к какому типу его десериализовать. Это приведет к тому, что ваши DTO будут заполнены дополнительными метаданными, но, по крайней мере, это альтернатива. Я бы настоятельно рекомендовал вместо этого обновлять ваши объекты с помощью дженериков. Это принесет вам пользу в долгосрочной перспективе.

Комментарии:

1. Фрагмент кода не будет компилироваться, IList<Роль> требуется имя.

2. Упс. Теперь это исправлено. Спасибо за это 🙂

3. Проблема в том, что это решение невозможно. Код является частью устаревшей системы, и существует множество классов, которые необходимо отредактировать. Кроме того, для исходного кода нет доступных модульных тестов, поэтому его нелегко реорганизовать.

4. @Beatles1692 Смотрите обновленный ответ 🙂 Я не принимаю аргумент «нет модульных тестов». Добавление общих ограничений к коллекциям должно только ужесточить вашу кодовую базу и упростить дальнейшую разработку.