diff --git a/docs/standard/serialization/system-text-json/snippets/how-to/csharp/RoundtripEnumSourceGeneration.cs b/docs/standard/serialization/system-text-json/snippets/how-to/csharp/RoundtripEnumSourceGeneration.cs index 30b2f0f97dbc9..bb3c80579ab6b 100644 --- a/docs/standard/serialization/system-text-json/snippets/how-to/csharp/RoundtripEnumSourceGeneration.cs +++ b/docs/standard/serialization/system-text-json/snippets/how-to/csharp/RoundtripEnumSourceGeneration.cs @@ -15,12 +15,7 @@ public static void Run() Precipitation = Precipitation.Sleet }; - var options = new JsonSerializerOptions - { - WriteIndented = true, - TypeInfoResolver = Context1.Default, - }; - string? jsonString = JsonSerializer.Serialize(weatherForecast, options); + string? jsonString = JsonSerializer.Serialize(weatherForecast, Context1.Default.WeatherForecastWithPrecipEnum); // Console.WriteLine($"JSON with enum as string:\n{jsonString}\n"); @@ -51,12 +46,7 @@ public static void Run() Precipitation = Precipitation2.Sleet }; - var options = new JsonSerializerOptions - { - WriteIndented = true, - TypeInfoResolver = Context2.Default, - }; - string? jsonString = JsonSerializer.Serialize(weatherForecast, options); + string? jsonString = JsonSerializer.Serialize(weatherForecast, Context2.Default.WeatherForecast2WithPrecipEnum); // Console.WriteLine($"JSON with enum as string:\n{jsonString}\n"); diff --git a/docs/standard/serialization/system-text-json/snippets/source-generation/csharp/BothModesNoOptions.cs b/docs/standard/serialization/system-text-json/snippets/source-generation/csharp/BothModesNoOptions.cs index 7c10a05bab851..f68433ab01298 100644 --- a/docs/standard/serialization/system-text-json/snippets/source-generation/csharp/BothModesNoOptions.cs +++ b/docs/standard/serialization/system-text-json/snippets/source-generation/csharp/BothModesNoOptions.cs @@ -1,6 +1,7 @@ // using System.Text.Json; using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; namespace BothModesNoOptions { @@ -40,22 +41,15 @@ public static void Main() // output: //Date=8/1/2019 12:00:00 AM - // - weatherForecast = JsonSerializer.Deserialize( - jsonString, typeof(WeatherForecast), SourceGenerationContext.Default) - as WeatherForecast; - // - Console.WriteLine($"Date={weatherForecast?.Date}"); - // output: - //Date=8/1/2019 12:00:00 AM - - // + // var sourceGenOptions = new JsonSerializerOptions { TypeInfoResolver = SourceGenerationContext.Default }; - weatherForecast = JsonSerializer.Deserialize(jsonString, sourceGenOptions); - // + weatherForecast = JsonSerializer.Deserialize( + jsonString, + (JsonTypeInfo)sourceGenOptions.GetTypeInfo(typeof(WeatherForecast))!); + // Console.WriteLine($"Date={weatherForecast?.Date}"); // output: //Date=8/1/2019 12:00:00 AM @@ -68,22 +62,11 @@ public static void Main() // output: //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"} - // + // jsonString = JsonSerializer.Serialize( - weatherForecast, typeof(WeatherForecast), SourceGenerationContext.Default); - // - Console.WriteLine(jsonString); - // output: - //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"} - - // - sourceGenOptions = new JsonSerializerOptions - { - TypeInfoResolver = SourceGenerationContext.Default - }; - - jsonString = JsonSerializer.Serialize(weatherForecast, sourceGenOptions); - // + weatherForecast!, + (JsonTypeInfo)sourceGenOptions.GetTypeInfo(typeof(WeatherForecast))!); + // Console.WriteLine(jsonString); // output: //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"} diff --git a/docs/standard/serialization/system-text-json/snippets/source-generation/csharp/SerializeOnlyWithOptions.cs b/docs/standard/serialization/system-text-json/snippets/source-generation/csharp/SerializeOnlyWithOptions.cs index 498d145c30b93..607039bef889b 100644 --- a/docs/standard/serialization/system-text-json/snippets/source-generation/csharp/SerializeOnlyWithOptions.cs +++ b/docs/standard/serialization/system-text-json/snippets/source-generation/csharp/SerializeOnlyWithOptions.cs @@ -45,19 +45,6 @@ public static void Main() // "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" - //} } } } diff --git a/docs/standard/serialization/system-text-json/source-generation.md b/docs/standard/serialization/system-text-json/source-generation.md index 5c9a796cbcfae..53662feb65b64 100644 --- a/docs/standard/serialization/system-text-json/source-generation.md +++ b/docs/standard/serialization/system-text-json/source-generation.md @@ -25,11 +25,7 @@ To use source generation with all defaults (both modes, default options): 1. Create a partial class that derives from . 1. Specify the type to serialize or deserialize by applying to the context class. -1. Call a method that either: - - - Takes a instance, or - - Takes a instance, or - - Takes a instance and you've set its property to the `Default` property of the context type. +1. Call a method that takes a instance. By default, both source generation modes (*metadata-based* and *serialization optimization*) are used if you don't specify one. For information about how to specify the mode to use, see [Specify source generation mode](#specify-source-generation-mode) later in this article. @@ -65,13 +61,9 @@ Using : :::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="SerializeWithTypeInfo"::: -Using : - -:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="SerializeWithContext"::: - -Using : +Using a `JsonSerializerOptions` instance by first resolving `JsonTypeInfo`: -:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="SerializeWithOptions"::: +:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="SerializeWithTypeInfoFromOptions"::: #### Deserialization examples @@ -79,13 +71,9 @@ Using : :::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="DeserializeWithTypeInfo"::: -Using : - -:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="DeserializeWithContext"::: - -Using : +Using a `JsonSerializerOptions` instance by first resolving `JsonTypeInfo`: -:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="DeserializeWithOptions"::: +:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="DeserializeWithTypeInfoFromOptions"::: ### Complete program example @@ -208,14 +196,22 @@ When using `JsonSourceGenerationOptionsAttribute` to specify serialization optio :::code language="csharp" source="snippets/source-generation/csharp/SerializeOnlyWithOptions.cs" id="SerializeWithTypeInfo"::: -- A `JsonSerializer.Serialize` method that takes a context. Pass it the `Default` static property of your context class. - - :::code language="csharp" source="snippets/source-generation/csharp/SerializeOnlyWithOptions.cs" id="SerializeWithContext"::: - If you call a method that lets you pass in your own instance of `Utf8JsonWriter`, the writer's setting is honored instead of the `JsonSourceGenerationOptionsAttribute.WriteIndented` option. If you create and use a context instance by calling the constructor that takes a `JsonSerializerOptions` instance, the supplied instance will be used instead of the options specified by `JsonSourceGenerationOptionsAttribute`. +> [!NOTE] +> Overloads that only take are generally unsuitable for Native AOT source-generation scenarios. For backward compatibility, these overloads can still fall back to reflection defaults, which is what trim analysis warns about. Prefer overloads that take `JsonTypeInfo` directly. +> +> If you need to flow contracts through an existing `JsonSerializerOptions` instance, resolve `JsonTypeInfo` first and then call a `JsonTypeInfo` overload: +> +> ```csharp +> JsonTypeInfo typeInfo = +> (JsonTypeInfo)options.GetTypeInfo(typeof(MyType)); +> string json = JsonSerializer.Serialize(value, typeInfo); +> MyType? model = JsonSerializer.Deserialize(json, typeInfo); +> ``` + The following code shows the preceding examples in a complete program: :::code language="csharp" source="snippets/source-generation/csharp/SerializeOnlyWithOptions.cs" id="All"::: @@ -252,7 +248,7 @@ Annotate the enumeration type with the class and annotate it with the attribute: +Create a source-generation context class and annotate it with the attribute: :::code language="csharp" source="snippets/how-to/csharp/RoundtripEnumSourceGeneration.cs" id="Context1"::: @@ -272,7 +268,7 @@ The resulting JSON looks like the following example: ### Blanket policy -Instead of using the type, you can apply a blanket policy to serialize enums as strings by using the . Create a class and annotate it with the *and * attributes: +Instead of using the type, you can apply a blanket policy to serialize enums as strings by using the . Create a source-generation context class and annotate it with the *and * attributes: :::code language="csharp" source="snippets/how-to/csharp/RoundtripEnumSourceGeneration.cs" id="Context2":::