Modos de generación de origen en System.Text.Json

La generación de origen se puede usar en dos modos: optimización basada en metadatos y serialización. En este artículo se describen los distintos modos.

Para obtener información sobre cómo usar los modos de generación de origen, vea Uso de la generación de origen en System.Text.Json.

Modo basado en metadatos

Puede usar la generación de origen para mover el proceso de recopilación de metadatos del tiempo de ejecución al tiempo de compilación. Durante la compilación se recopilan metadatos y se generan archivos de código fuente. Los archivos de código fuente generados se compilan automáticamente como parte integral de la aplicación. Esta técnica elimina la recopilación de metadatos en tiempo de ejecución, lo que mejora el rendimiento de la serialización y la deserialización.

Las mejoras de rendimiento proporcionadas por la generación de origen pueden ser considerables. Por ejemplo, los resultados de las pruebas han mostrado hasta un 40 % o más de reducción del tiempo de inicio, de reducción de memoria privada, de aumento de la velocidad de rendimiento (en modo de optimización de serialización) y de reducción del tamaño de la aplicación.

Problemas conocidos

Solo las propiedades y los campos public se admiten de manera predeterminada en cualquiera de los modos de serialización. Sin embargo, el modo de reflexión admite el uso de privatedescriptores de acceso , mientras que el modo de generación de orígenes no lo admite. Por ejemplo, puede aplicar el atributo JsonInclude a una propiedad que tenga un establecedor o captador private y se serializará en modo de reflexión. El modo de generación de orígenes solo admite descriptores de acceso public o internal de propiedades public. Si establece [JsonInclude] en descriptores de acceso no públicos y elige el modo de generación de orígenes, se producirá una excepción NotSupportedException en tiempo de ejecución.

Solo las propiedades y los campos public se admiten de manera predeterminada en cualquiera de los modos de serialización. Sin embargo, el modo de reflexión admite el uso de miembros private y privatedescriptores de acceso , mientras que el modo de generación de orígenes no lo admite. Por ejemplo, si aplica el atributo JsonInclude a una propiedad private o una propiedad que tiene un establecedor o captador private, se serializará en modo de reflexión. El modo de generación de orígenes solo admite miembros public o internal y descriptores de acceso public o internal de propiedades public. Si establece [JsonInclude] en miembros private o descriptores de acceso y elige el modo de generación de orígenes, se producirá una excepción NotSupportedException en tiempo de ejecución.

Para obtener información sobre otros problemas conocidos de la generación de origen, vea los problemas de GitHub etiquetados como "source-generator" en el repositorio dotnet/runtime.

Modo de optimización de serialización (ruta de acceso rápida)

JsonSerializer tiene muchas características que personalizan la salida de la serialización, como las directivas de nomenclatura y la conservación de referencias. La compatibilidad con todas esas características provoca cierta sobrecarga de rendimiento. La generación de origen puede mejorar el rendimiento de la serialización mediante la generación de código optimizado que usa Utf8JsonWriter directamente.

El código optimizado no admite todas las características de serialización que JsonSerializer sí. El serializador detecta si se puede usar el código optimizado y recurre al código de serialización predeterminado si se especifican opciones no admitidas. Por ejemplo, JsonNumberHandling.AllowReadingFromString no es aplicable a la escritura, por lo que la especificación de esta opción no hace que se recurra al código predeterminado.

En la tabla siguiente se muestran las opciones de JsonSerializerOptions compatibles con la serialización de ruta de acceso rápido:

Opción de serialización Compatible con la ruta de acceso rápida
AllowTrailingCommas ✔️
Converters
DefaultBufferSize ✔️
DefaultIgnoreCondition ✔️
DictionaryKeyPolicy
Encoder
IgnoreNullValues
IgnoreReadOnlyFields ✔️
IgnoreReadOnlyProperties ✔️
IncludeFields ✔️
MaxDepth ✔️
NumberHandling
PropertyNamingPolicy ✔️
ReferenceHandler
TypeInfoResolver ✔️
WriteIndented ✔️

(No se admiten las siguientes opciones porque solo se aplican a la deserialización: PropertyNameCaseInsensitive, ReadCommentHandling y UnknownTypeHandling).

En la tabla siguiente se muestran los atributos admitidos por la serialización de ruta de acceso rápida:

Atributo Compatible con la ruta de acceso rápida
JsonConstructorAttribute
JsonConverterAttribute
JsonDerivedTypeAttribute ✔️
JsonExtensionDataAttribute
JsonIgnoreAttribute ✔️
JsonIncludeAttribute ✔️
JsonNumberHandlingAttribute
JsonPolymorphicAttribute ✔️
JsonPropertyNameAttribute ✔️
JsonPropertyOrderAttribute ✔️
JsonRequiredAttribute ✔️

Si se especifica una opción o atributo no compatible para un tipo, el serializador vuelve al modo de metadatos, suponiendo que el generador de origen se haya configurado para generar metadatos. En ese caso, el código optimizado no se usa al serializar ese tipo, pero se puede usar con otros tipos. Por lo tanto, es importante realizar pruebas de rendimiento con las opciones y cargas de trabajo para determinar cómo de ventajoso resulta en realidad el modo de optimización de serialización. Además, la capacidad de volver al código JsonSerializer requiere el modo de recopilación de metadatos. Si selecciona solo el modo de optimización de serialización, es posible que se produzca un error en la serialización de tipos u opciones que necesiten recurrir al código JsonSerializer.

Consulte también