Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
// </Serialize>
Console.WriteLine($"JSON with enum as string:\n{jsonString}\n");

Expand Down Expand Up @@ -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);
// </Serialize2>
Console.WriteLine($"JSON with enum as string:\n{jsonString}\n");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// <All>
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;

namespace BothModesNoOptions
{
Expand Down Expand Up @@ -40,22 +41,15 @@ public static void Main()
// output:
//Date=8/1/2019 12:00:00 AM

// <DeserializeWithContext>
weatherForecast = JsonSerializer.Deserialize(
jsonString, typeof(WeatherForecast), SourceGenerationContext.Default)
as WeatherForecast;
// </DeserializeWithContext>
Console.WriteLine($"Date={weatherForecast?.Date}");
// output:
//Date=8/1/2019 12:00:00 AM

// <DeserializeWithOptions>
// <DeserializeWithTypeInfoFromOptions>
var sourceGenOptions = new JsonSerializerOptions
{
TypeInfoResolver = SourceGenerationContext.Default
};
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, sourceGenOptions);
// </DeserializeWithOptions>
weatherForecast = JsonSerializer.Deserialize(
jsonString,
(JsonTypeInfo<WeatherForecast>)sourceGenOptions.GetTypeInfo(typeof(WeatherForecast))!);
// </DeserializeWithTypeInfoFromOptions>
Console.WriteLine($"Date={weatherForecast?.Date}");
// output:
//Date=8/1/2019 12:00:00 AM
Expand All @@ -68,22 +62,11 @@ public static void Main()
// output:
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}

// <SerializeWithContext>
// <SerializeWithTypeInfoFromOptions>
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), SourceGenerationContext.Default);
// </SerializeWithContext>
Console.WriteLine(jsonString);
// output:
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}

// <SerializeWithOptions>
sourceGenOptions = new JsonSerializerOptions
{
TypeInfoResolver = SourceGenerationContext.Default
};

jsonString = JsonSerializer.Serialize<WeatherForecast>(weatherForecast, sourceGenOptions);
// </SerializeWithOptions>
weatherForecast!,
(JsonTypeInfo<WeatherForecast>)sourceGenOptions.GetTypeInfo(typeof(WeatherForecast))!);
// </SerializeWithTypeInfoFromOptions>
Console.WriteLine(jsonString);
// output:
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,6 @@ public static void Main()
// "summary": "Hot"
//}

// Serialize using Default context
// and options specified by [JsonSourceGenerationOptions].
// <SerializeWithContext>
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), SerializationModeOptionsContext.Default);
// </SerializeWithContext>
Console.WriteLine(jsonString);
// output:
//{
// "date": "2019-08-01T00:00:00",
// "temperatureCelsius": 0,
// "summary": "Hot"
//}
}
}
}
Expand Down
42 changes: 19 additions & 23 deletions docs/standard/serialization/system-text-json/source-generation.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ To use source generation with all defaults (both modes, default options):

1. Create a partial class that derives from <xref:System.Text.Json.Serialization.JsonSerializerContext>.
1. Specify the type to serialize or deserialize by applying <xref:System.Text.Json.Serialization.JsonSerializableAttribute> to the context class.
1. Call a <xref:System.Text.Json.JsonSerializer> method that either:

- Takes a <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfo`1> instance, or
- Takes a <xref:System.Text.Json.Serialization.JsonSerializerContext> instance, or
- Takes a <xref:System.Text.Json.JsonSerializerOptions> instance and you've set its <xref:System.Text.Json.JsonSerializerOptions.TypeInfoResolver?displayProperty=nameWithType> property to the `Default` property of the context type.
1. Call a <xref:System.Text.Json.JsonSerializer> method that takes a <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfo`1> 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.

Expand Down Expand Up @@ -65,27 +61,19 @@ Using <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfo`1>:

:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="SerializeWithTypeInfo":::

Using <xref:System.Text.Json.Serialization.JsonSerializerContext>:

:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="SerializeWithContext":::

Using <xref:System.Text.Json.JsonSerializerOptions>:
Using a `JsonSerializerOptions` instance by first resolving `JsonTypeInfo<T>`:

:::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

Using <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfo`1>:

:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="DeserializeWithTypeInfo":::

Using <xref:System.Text.Json.Serialization.JsonSerializerContext>:

:::code language="csharp" source="snippets/source-generation/csharp/BothModesNoOptions.cs" id="DeserializeWithContext":::

Using <xref:System.Text.Json.JsonSerializerOptions>:
Using a `JsonSerializerOptions` instance by first resolving `JsonTypeInfo<T>`:

:::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

Expand Down Expand Up @@ -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 <xref:System.Text.Json.JsonWriterOptions.Indented> 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 <xref:System.Text.Json.JsonSerializerOptions> 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<T>` directly.
>
> If you need to flow contracts through an existing `JsonSerializerOptions` instance, resolve `JsonTypeInfo<T>` first and then call a `JsonTypeInfo<T>` overload:
>
> ```csharp
> JsonTypeInfo<MyType> typeInfo =
> (JsonTypeInfo<MyType>)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":::
Expand Down Expand Up @@ -252,7 +248,7 @@ Annotate the enumeration type with the <xref:System.Text.Json.Serialization.Json

:::code language="csharp" source="snippets/how-to/csharp/WeatherForecast.cs" id="WFWithConverterEnum":::

Create a <xref:System.Text.Json.Serialization.JsonSerializerContext> class and annotate it with the <xref:System.Text.Json.Serialization.JsonSerializableAttribute> attribute:
Create a source-generation context class and annotate it with the <xref:System.Text.Json.Serialization.JsonSerializableAttribute> attribute:

:::code language="csharp" source="snippets/how-to/csharp/RoundtripEnumSourceGeneration.cs" id="Context1":::

Expand All @@ -272,7 +268,7 @@ The resulting JSON looks like the following example:

### Blanket policy

Instead of using the <xref:System.Text.Json.Serialization.JsonStringEnumConverter`1> type, you can apply a blanket policy to serialize enums as strings by using the <xref:System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute>. Create a <xref:System.Text.Json.Serialization.JsonSerializerContext> class and annotate it with the <xref:System.Text.Json.Serialization.JsonSerializableAttribute> *and <xref:System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute>* attributes:
Instead of using the <xref:System.Text.Json.Serialization.JsonStringEnumConverter`1> type, you can apply a blanket policy to serialize enums as strings by using the <xref:System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute>. Create a source-generation context class and annotate it with the <xref:System.Text.Json.Serialization.JsonSerializableAttribute> *and <xref:System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute>* attributes:

:::code language="csharp" source="snippets/how-to/csharp/RoundtripEnumSourceGeneration.cs" id="Context2":::

Expand Down