#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
.
Свойства .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 Смотрите обновленный ответ 🙂 Я не принимаю аргумент «нет модульных тестов». Добавление общих ограничений к коллекциям должно только ужесточить вашу кодовую базу и упростить дальнейшую разработку.