Uso de la generación de origen en System.Text.Json
Artikulua
La generación de origen de System.Text.Json está disponible en .NET 6 y versiones posteriores. Cuando se usa en una aplicación, la versión del lenguaje de la aplicación debe ser C# 9.0 o posterior. En este artículo se muestra cómo usar la serialización respaldada por la generación de origen en las aplicaciones.
Para obtener información sobre los diferentes modos de generación de origen, consulte Modos de generación de origen.
Uso de los valores predeterminados de la generación de origen
Para usar la generación de origen con todos los valores predeterminados (ambos modos, opciones predeterminadas):
De forma predeterminada, se usan ambos modos de generación de origen si no se especifica uno. Para obtener información sobre cómo especificar el modo que se va a usar, vea Especificar el modo de generación de origen más adelante en este artículo.
Este es el tipo que se usa en los ejemplos siguientes:
No es necesario especificar explícitamente los tipos de miembros WeatherForecast con atributos [JsonSerializable]. Los miembros declarados como object son una excepción a esta regla. El tipo de runtime de un miembro declarado como object debe especificarse. Por ejemplo, supongamos que tiene la siguiente clase:
C#
publicclassWeatherForecast
{
publicobject? Data { get; set; }
public List<object>? DataList { get; set; }
}
Y sabe que en tiempo de ejecución puede tener objetos boolean y int:
C#
WeatherForecast wf = new() { Data = true, DataList = new List<object> { true, 1 } };
A continuación, boolean y int deben declararse como [JsonSerializable]:
Para especificar la generación de origen para una colección, use [JsonSerializable] con el tipo de colección . Por ejemplo: [JsonSerializable(typeof(List<WeatherForecast>))].
Los métodos JsonSerializer que usan la generación de origen
En los ejemplos anteriores, la propiedad Default estática del tipo de contexto proporciona una instancia del tipo de contexto con opciones predeterminadas. La instancia de contexto proporciona una propiedad WeatherForecast que devuelve una instancia JsonTypeInfo<WeatherForecast>. Puede especificar un nombre diferente para esta propiedad mediante la propiedad TypeInfoPropertyName del atributo [JsonSerializable].
Se puede especificar el modo basado en metadatos o el modo de optimización de serialización para un contexto completo, que puede incluir varios tipos. O bien, puede especificar el modo para un tipo individual. Si lo hace, la especificación del modo para un tipo gana.
En .NET 7 y versiones anteriores, esta limitación también se aplica a las sobrecargas sincrónicas de JsonSerializer.Serialize que aceptan Stream. A partir de .NET 8, aunque la serialización de streaming requiere modelos basados en metadatos, se revertirá a la ruta de acceso rápida si se sabe que las cargas son lo suficientemente pequeñas como para ajustarse al tamaño de búfer predeterminado. Para obtener más información, vea https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#json.
Deshabilitar los valores predeterminados de reflexión
Dado que System.Text.Json usa la reflexión de forma predeterminada, llamar a un método de serialización básico puede interrumpir las aplicaciones AOT nativas, lo que no admite todas las API de reflexión necesarias. Estas interrupciones pueden ser difíciles de diagnosticar, ya que pueden ser impredecibles y las aplicaciones a menudo se depuran mediante el runtime de CoreCLR, donde funciona la reflexión. En su lugar, si deshabilita explícitamente la serialización basada en reflexión, las interrupciones serán más fáciles de diagnosticar. El código que usa la serialización basada en reflexión hará que se produzca un InvalidOperationException con un mensaje descriptivo mostrado en tiempo de ejecución.
Para deshabilitar la reflexión predeterminada en la aplicación, establezca la propiedad MSBuild JsonSerializerIsReflectionEnabledByDefault en false en el archivo del proyecto:
El comportamiento de esta propiedad es coherente, independientemente del runtime, ya sea CoreCLR o AOT nativo.
Si no se especifica esta propiedad y PublishTrimmed estuviera habilitado, la serialización basada en reflexión se deshabilitará automáticamente.
Es posible comprobar mediante programación si la reflexión está deshabilitada gracias a la propiedad JsonSerializer.IsReflectionEnabledByDefault. El siguiente fragmento de código muestra cómo se configura el serializador en función de si la reflexión está habilitada:
Dado que la propiedad se trata como una constante en tiempo de vínculo, el método anterior no enraíza el solucionador basado en reflexión en las aplicaciones que se ejecuten en AOT nativo.
Especificar opciones
En .NET 8 y versiones posteriores, la mayoría de las opciones que se pueden establecer mediante JsonSerializerOptions también se pueden establecer con el atributo JsonSourceGenerationOptionsAttribute. La ventaja de establecer las opciones a través del atributo es que la configuración se especifica en tiempo de compilación, lo que garantizará que la propiedad MyContext.Default generada esté preconfigurada con todos los conjuntos de opciones pertinentes.
Si llama a un método que le permite pasar su propia instancia de Utf8JsonWriter, se respeta la configuración del escritor Indented en lugar de la opción JsonSourceGenerationOptionsAttribute.WriteIndented.
Si crea y usa una instancia de contexto llamando al constructor que toma una instancia JsonSerializerOptions, se usará la instancia proporcionada en lugar de las opciones especificadas por JsonSourceGenerationOptionsAttribute.
Estos son los ejemplos anteriores en un programa completo:
C#
using System.Text.Json;
using System.Text.Json.Serialization;
namespaceSerializeOnlyWithOptions
{
publicclassWeatherForecast
{
public DateTime Date { get; set; }
publicint TemperatureCelsius { get; set; }
publicstring? Summary { get; set; }
}
[JsonSourceGenerationOptions(
WriteIndented = true,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(WeatherForecast))]
internalpartialclassSerializationModeOptionsContext : JsonSerializerContext
{
}
publicclassProgram
{
publicstaticvoidMain()
{
string jsonString;
WeatherForecast weatherForecast = new()
{ Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" };
// Serialize using TypeInfo<TValue> provided by the context// and options specified by [JsonSourceGenerationOptions].
jsonString = JsonSerializer.Serialize(
weatherForecast, SerializationModeOptionsContext.Default.WeatherForecast);
Console.WriteLine(jsonString);
// output://{// "date": "2019-08-01T00:00:00",// "temperatureCelsius": 0,// "summary": "Hot"//}// Serialize using Default context// and options specified by [JsonSourceGenerationOptions].
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), SerializationModeOptionsContext.Default);
Console.WriteLine(jsonString);
// output://{// "date": "2019-08-01T00:00:00",// "temperatureCelsius": 0,// "summary": "Hot"//}
}
}
}
var options = new JsonSerializerOptions
{
TypeInfoResolver = JsonTypeInfoResolver.Combine(ContextA.Default, ContextB.Default, ContextC.Default);
};
A partir de .NET 8, si después desea anteponer o anexar otro contexto, es posible hacerlo mediante la propiedad JsonSerializerOptions.TypeInfoResolverChain. El orden de la cadena es significativo: JsonSerializerOptions consulta cada uno de los solucionadores en el orden especificado y devuelve el primer resultado que no sea NULL.
C#
options.TypeInfoResolverChain.Add(ContextD.Default); // Append to the end of the list.
options.TypeInfoResolverChain.Insert(0, ContextE.Default); // Insert at the beginning of the list.
Para serializar los nombres de enumeración como cadenas mediante la generación de origen, use el convertidor JsonStringEnumConverter<TEnum>. (El tipo no genérico JsonStringEnumConverter no es compatible con el entorno de ejecución de AOT nativo).
Eduki honen iturburua GitHub-en aurki daiteke, bertan arazoak eta aldaketak egiteko eskaerak sortu eta berrikus ditzakezu. Informazio gehiagorako, ikusi gure kolaboratzaileen gida.
.NET oharrak
.NET iturburu irekiko proiektu bat da. Hautatu esteka bat oharrak bidaltzeko:
Bat egin IAren soluzio eskalagarrien soluzioak sortzeko topaketa sortarekin, mundu errealaren erabilera-kasuetan oinarrituak, beste garatzaile eta aditu batzuekin.
Learn about the .NET 7 breaking change in serialization where the System.Text.Json source generator no longer fall backs to reflection-based serialization for unrecognized types.
Learn about the .NET 8 breaking change in System.Text.Json serialization where projects with PublishTrimmed enabled now fail reflection-based serialization by default.