System.Text.Json 中的源生成模式

源生成采用两种模式:基于元数据和序列化优化。 本文介绍不同的模式。

有关如何使用源生成模式的信息,请参阅如何在 System.Text.Json 中使用源生成

基于元数据的模式

可以使用源生成将元数据收集进程从运行时移到编译时。 在编译期间,系统将收集元数据并生成源代码文件。 生成的源代码文件会自动编译为应用程序的一个整型部分。 使用此方法便无需进行运行时元数据集合,这可提高序列化和反序列化的性能。

源生成提供的性能改进可能很大。 例如,测试结果显示出可获得高达 40% 或更高的启动时间缩减、专用内存缩减、吞吐速度增加(在序列化优化模式下)和应用大小减小。

已知问题

在任一序列化模式下,默认只支持 public 属性和字段。 但是,反射模式支持使用 private 访问器,而源生成模式不支持。 例如,可将 JsonInclude 特性应用于具有 private setter 或 getter 的属性,并且该特性将在反射模式下序列化。 源生成模式只支持 public 属性的 publicinternal 访问器。 如果在非公共访问器上设置 [JsonInclude] 并选择源生成模式,则会在运行时引发 NotSupportedException

在任一序列化模式下,默认只支持 public 属性和字段。 但是,反射模式支持使用 private 成员和 private 访问器,而源生成模式不支持。 例如,如果将 JsonInclude 属性应用于 private 属性或具有 private setter 或 getter 的属性,它将在反射模式下序列化。 源生成模式仅支持 publicinternal 成员以及 public 属性的 publicinternal 访问器。 如果在 private 成员或访问器上设置 [JsonInclude] 并选择源生成模式,则会在运行时引发 NotSupportedException

有关源生成的其他已知问题的信息,请参阅 dotnet/runtime 存储库中标记为“source-generator”的 GitHub 问题

序列化优化(快速路径)模式

JsonSerializer 具有许多自定义序列化输出的功能,例如命名策略保留引用。 对所有这些功能的支持会导致一些性能开销。 源生成可以通过生成直接使用 Utf8JsonWriter 的优化代码来提高序列化性能。

该优化代码不支持 JsonSerializer 所有序列化功能。 如果指定了不受支持的选项,则序列化程序将检测是否可以使用该优化代码并回退到默认序列化代码。 例如,JsonNumberHandling.AllowReadingFromString 不适用于写入,因此,指定此选项不会导致回退到默认代码。

下表显示了快速路径序列化所支持的 JsonSerializerOptions 中的选项:

序列化选项 支持快速路径
AllowTrailingCommas
Converters
DefaultBufferSize
DefaultIgnoreCondition
DictionaryKeyPolicy
Encoder
IgnoreNullValues
IgnoreReadOnlyFields
IgnoreReadOnlyProperties
IncludeFields
MaxDepth
NumberHandling
PropertyNamingPolicy
ReferenceHandler
TypeInfoResolver
WriteIndented

(由于以下选项仅适用于反序列化,因此不受支持:PropertyNameCaseInsensitiveReadCommentHandlingUnknownTypeHandling。)

下表显示了快速路径序列化所支持的属性:

Attribute 支持快速路径
JsonConstructorAttribute
JsonConverterAttribute
JsonDerivedTypeAttribute
JsonExtensionDataAttribute
JsonIgnoreAttribute
JsonIncludeAttribute
JsonNumberHandlingAttribute
JsonPolymorphicAttribute
JsonPropertyNameAttribute
JsonPropertyOrderAttribute
JsonRequiredAttribute

如果为类型指定了不受支持的选项或属性,则序列化程序将返回到元数据模式,前提是源生成器已配置为生成元数据。 在这种情况下,不会在序列化该类型时使用优化代码,但可以将优化代码用于其他类型。 因此,请务必使用选项和工作负载进行性能测试,以确定序列化优化模式实际可带来多少益处。 此外,回退到 JsonSerializer 代码的功能需要使用元数据收集模式。 如果只选择了序列化优化模式,则对于需要回退到 JsonSerializer 代码的类型或选项,序列化可能会失败。

另请参阅