Ответ 1
Отличный вопрос. Я не видел четкую документацию, в которой говорится, что если вы предпочитаете писать пользовательский ContractResolver
или пользовательский JsonConverter
для решения определенного типа проблем. Они действительно делают разные вещи, но есть некоторые совпадения между тем, какие проблемы могут быть решены каждым. Я написал много слов, отвечая на вопросы StackOverflow, поэтому картина со временем стала мне более понятной. Ниже я принимаю это.
ContractResolver
Контракторный преобразователь всегда используется Json.Net и регулирует поведение сериализации/десериализации на широком уровне. Если в настройках нет настраиваемого преобразователя, используется DefaultContractResolver
. Ответчик отвечает за определение:
- какой контракт имеет каждый тип (т.е. он примитив, массив/список, словарь, динамический,
JObject
, простой старый объект, и т.д.); - какие свойства относятся к типу (если есть), и каковы их имена, типы и доступность;
- что attributes были применены (например,
[JsonProperty]
,[JsonIgnore]
,[JsonConverter]
и т.д.) и - как эти атрибуты должны влиять на сериализацию (де) каждого свойства (или класса).
Вообще говоря, если вы хотите настроить некоторые аспекты сериализации или десериализации в широком диапазоне классов, вам, вероятно, потребуется использовать ContractResolver
для этого. Вот несколько примеров вещей, которые вы можете настроить с помощью ContractResolver
:
- Измените контракт, используемый для типа
- Измените оболочку имен свойств при сериализации
- Программно применять атрибуты к свойствам без необходимости изменять классы (особенно полезно, если вы не контролируете источник указанных классов)
- Программно не применять (игнорировать) атрибуты, применяемые к определенным классам
- Условно упорядочить свойства
- Внедрение пользовательских атрибутов и применение некоторого пользовательского поведения на основе этих атрибутов
JsonConverter
В отличие от ContractResolver
фокус a JsonConverter
более узкий: он действительно предназначен для обработки сериализации или десериализации для одного типа или небольшого подмножества связанных типов. Кроме того, он работает на более низком уровне, чем распознаватель. Когда конвертер получает ответственность за тип, он полностью контролирует, как JSON считывается или записывается для этого типа: он напрямую использует JsonReader
и JsonWriter
, чтобы выполнить свою работу. Другими словами, он может изменить форму JSON для этого типа. В то же время конвертер отделен от "большой картинки" и не имеет доступа к контекстной информации, такой как родительский объект сериализуемого объекта или атрибуты свойств, которые были с ним использованы. Вот несколько примеров проблем, которые вы можете решить с помощью JsonConverter
:
- Проблемы создания экземпляра дескриптора объекта при десериализации
- десериализовать интерфейс, используя информацию в JSON, чтобы решить, какой конкретный класс необходимо создать
- Deserialize JSON, который иногда является единственным объектом, а иногда и массивом объектов
- Deserialize JSON, который может быть массивом или вложенным массивом
- Пропустить нежелательные элементы при десериализации из массива смешанных типов
- Deserialize для объекта, которому не нужен конструктор по умолчанию
- Изменить способ форматирования или интерпретации значений
- Сериализовать десятичные значения как локализованные строки
- Преобразовать decimal.MinValue в пустую строку и обратно (для использования с унаследованной системой)
- Сериализовать даты с несколькими различными форматами
- Игнорировать смещения UTC при десериализации дат
- Сделать Json.Net-вызов
ToString()
при сериализации типа
- Перевод между различными структурами JSON и объектов
- Дезертициализировать вложенный массив смешанных значений в список элементов
- десериализовать массив объектов с разными именами
- Сериализация/десериализация пользовательского словаря со сложными ключами
- Сериализовать пользовательскую коллекцию IEnumerable в качестве словаря
- Сгладить вложенную структуру JSON в более простую структуру объектов
- Разверните простую структуру объекта в более сложную структуру JSON
- Сериализовать список объектов только как список идентификаторов
- Уничтожить список объектов JSON, содержащих GUID, в список идентификаторов GUID
- Работа над проблемами (de), сериализация определенных типов .NET