Выбор отражения или создания источника в System.Text.Json

По умолчанию использует отражение времени выполнения для сбора метаданных, System.Text.Json необходимых для доступа к свойствам объектов для сериализации и десериализации. В качестве альтернативы System.Text.Json в версии 6.0 и более поздних версий можно использовать функцию создания источника C#, чтобы повысить производительность, уменьшить использование частной памяти и упростить обрезку сборок, что сокращает размер приложения.

Вы можете использовать версию 6.0 или более поздние версии System.Text.Json в проектах, предназначенных для более ранних платформ. Дополнительные сведения см. в разделе Как получить библиотеку.

В этой статье описываются варианты и приводятся рекомендации по выбору оптимального подхода для вашего сценария.

Общие сведения

Выберите режимы отражения или создания источника на основе следующих преимуществ, которые предлагает каждый из них:

Преимущество Отражение Создание источника:
Коллекция метаданных
Создание источника:
Оптимизация сериализации
Проще кодировать и отлаживать. ✔️
Поддерживает методы доступа, не являющиеся открытыми. ✔️
Поддерживает обязательные свойства. ✔️ ✔️ ✔️
Поддерживает свойства только для инициализации. ✔️ ✔️ ✔️
Поддерживает все доступные настройки сериализации. ✔️
Сокращает время запуска. ✔️
Снижает использование частной памяти. ✔️ ✔️
Исключает отражение во время выполнения. ✔️ ✔️
Упрощает сокращение размера приложения, безопасного для обрезки. ✔️ ✔️
Увеличивает пропускную способность сериализации. ✔️

Общие сведения

Выберите режимы отражения или создания источника на основе следующих преимуществ, которые предлагает каждый из них:

Преимущество Отражение Создание источника:
Коллекция метаданных
Создание источника:
Оптимизация сериализации
Проще кодировать и отлаживать. ✔️
Поддерживает методы доступа, не являющиеся открытыми. ✔️
Поддерживает обязательные свойства. ✔️
Поддерживает свойства только для инициализации. ✔️
Поддерживает все доступные настройки сериализации. ✔️
Сокращает время запуска. ✔️
Снижает использование частной памяти. ✔️ ✔️
Исключает отражение во время выполнения. ✔️ ✔️
Упрощает сокращение размера приложения, безопасного для обрезки. ✔️ ✔️
Увеличивает пропускную способность сериализации. ✔️

В следующих разделах описываются эти варианты и их относительные преимущества.

System.Text.Json — метаданные изображения.

Для сериализации или десериализации типа требуется информация о том, JsonSerializer как получить доступ к членам типа. JsonSerializer требуется следующая информация:

  • Как получить доступ к свойствам и полям для сериализации.
  • Как получить доступ к конструктору, методу задания свойств и полям для десериализации.
  • Сведения о том, какие атрибуты использовались для настройки сериализации или десериализации.
  • Конфигурация времени выполнения из JsonSerializerOptions.

Эти сведения называются метаданными.

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

Создание источника — режим сбора метаданных

Создание исходного кода можно использовать для перемещения процесса сбора метаданных из времени выполнения в время компиляции. Во время компиляции собираются метаданные и создаются файлы исходного кода. Созданные файлы исходного кода автоматически компилируются как неотъемлемая часть приложения. Этот метод исключает сбор метаданных во время выполнения, что повышает производительность сериализации и десериализации.

Повышение производительности при создании источника может быть существенным. Например, результаты теста показали сокращение времени запуска до 40 % или более, сокращение частной памяти, увеличение скорости пропускной способности (в режиме оптимизации сериализации) и уменьшение размера приложения.

Известные проблемы

По умолчанию* в обоих режимах сериализации поддерживаются только public свойства и поля. Однако режим отражения поддерживает использование privateметодов доступа , а режим создания источника — нет. Например, можно применить атрибут JsonInclude к свойству, у которого private есть метод задания или метода получения, и оно будет сериализовано в режиме отражения. Режим создания источника поддерживает только public методы public доступа свойств или internal . Если задать [JsonInclude] для методов доступа, не являющихся открытыми, и выбрать режим создания источника, NotSupportedException во время выполнения будет выдано исключение .

Как в режиме отражения, так и в режиме создания источника:

  • Поддерживаются* только public свойства и public поля.
  • Для десериализации можно использовать только public конструкторы.

*Начиная с .NET 7 можно использовать пользовательские контракты JSON для включения private свойств и полей в сериализацию.

Сведения о других известных проблемах, связанных с созданием источника, см. в статье Проблемы с GitHub, которые помечены как source-generator в репозитории dotnet/runtime .

Режим оптимизации сериализации

JsonSerializer имеет множество функций, которые настраивают выходные данные сериализации, например имена свойств верблюда и сохранение ссылок. Поддержка всех этих функций приводит к некоторым издержкам производительности. Создание источника может повысить производительность сериализации путем создания оптимизированного кода, который использует Utf8JsonWriter напрямую.

Оптимизированный код не поддерживает все поддерживаемые функции JsonSerializer сериализации. Сериализатор определяет, можно ли использовать оптимизированный код, и возвращается к коду сериализации по умолчанию, если указаны неподдерживаемые параметры. Например, JsonNumberHandling.AllowReadingFromString неприменимо к записи, поэтому указание этого параметра не приводит к откату кода по умолчанию.

В следующей таблице показано, какие параметры в JsonSerializerOptions поддерживаются оптимизированным кодом сериализации:

Параметр сериализации Поддерживается оптимизированным кодом
Converters
DefaultIgnoreCondition ✔️
DictionaryKeyPolicy
Encoder
IgnoreNullValues
IgnoreReadOnlyFields ✔️
IgnoreReadOnlyProperties ✔️
IncludeFields ✔️
NumberHandling
PropertyNamingPolicy ✔️
ReferenceHandler
TypeInfoResolver ✔️
WriteIndented ✔️

В следующей таблице показано, какие атрибуты поддерживаются оптимизированным кодом сериализации:

attribute Поддерживается оптимизированным кодом
JsonConverterAttribute
JsonDerivedTypeAttribute ✔️
JsonExtensionDataAttribute
JsonIgnoreAttribute ✔️
JsonIncludeAttribute ✔️
JsonNumberHandlingAttribute
JsonPolymorphicAttribute ✔️
JsonPropertyNameAttribute ✔️
JsonRequiredAttribute ✔️

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

Использование режимов создания источника

В большей части документации System.Text.Json показано, как написать код, использующий режим отражения. Сведения об использовании режимов создания источника см. в разделе Использование создания источников в System.Text.Json.

См. также раздел