Skip to content
Open
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 @@ -16,9 +16,7 @@ public class WeatherForecast
// <DefineContext>
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}
internal partial class SourceGenerationContext : JsonSerializerContext { }
// </DefineContext>

public class Program
Expand All @@ -35,7 +33,7 @@ public static void Main()
WeatherForecast? weatherForecast;

// <DeserializeWithTypeInfo>
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
weatherForecast = JsonSerializer.Deserialize(
jsonString, SourceGenerationContext.Default.WeatherForecast);
// </DeserializeWithTypeInfo>
Console.WriteLine($"Date={weatherForecast?.Date}");
Expand All @@ -56,9 +54,7 @@ public static void Main()
{
TypeInfoResolver = SourceGenerationContext.Default
};
weatherForecast = JsonSerializer.Deserialize(
jsonString, typeof(WeatherForecast), sourceGenOptions)
as WeatherForecast;
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString, sourceGenOptions);
// </DeserializeWithOptions>
Console.WriteLine($"Date={weatherForecast?.Date}");
// output:
Expand Down Expand Up @@ -86,8 +82,7 @@ public static void Main()
TypeInfoResolver = SourceGenerationContext.Default
};

jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), sourceGenOptions);
jsonString = JsonSerializer.Serialize<WeatherForecast>(weatherForecast, sourceGenOptions);
// </SerializeWithOptions>
Console.WriteLine(jsonString);
// output:
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public static void Main()
// Serialize with context that selects metadata mode only for WeatherForecast only.
// <SerializeWFContext>
jsonString = JsonSerializer.Serialize(
weatherForecast!,
weatherForecast,
MetadataOnlyWeatherForecastOnlyContext.Default.WeatherForecast);
// </SerializeWFContext>
Console.WriteLine(jsonString);
Expand All @@ -70,7 +70,7 @@ public static void Main()
// Serialize with context that selects metadata mode only.
// <SerializeMetadataOnlyContext>
jsonString = JsonSerializer.Serialize(
weatherForecast!, MetadataOnlyContext.Default.WeatherForecast);
weatherForecast, MetadataOnlyContext.Default.WeatherForecast);
// </SerializeMetadataOnlyContext>
Console.WriteLine(jsonString);
// output:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// <All>
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

Expand Down Expand Up @@ -27,7 +26,7 @@ public class Program
public static void Main()
{
// <WFInit>
WeatherForecast wf = new() { Data = true, DataList = new List<object> { true, 1 } };
WeatherForecast wf = new() { Data = true, DataList = [true, 1] };
// </WFInit>
string json = JsonSerializer.Serialize(wf, WeatherForecastContext.Default.WeatherForecast);
Console.WriteLine(json);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace SystemTextJsonSamples
namespace SystemTextJsonSamples
{
public class Program
{
Expand All @@ -17,8 +12,6 @@ static void Main()
MetadataOnlyNoOptions.Program.Main();
Console.WriteLine("\n============================= SerializeOnlyWithOptions\n");
SerializeOnlyWithOptions.Program.Main();
Console.WriteLine("\n============================= JsonSerializerOptionsExample\n");
JsonSerializerOptionsExample.Program.Main();
Console.WriteLine("\n============================= ObjectProperties\n");
ObjectProperties.Program.Main();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ public static void Main()
{
string jsonString;
WeatherForecast weatherForecast = new()
{ Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" };
{ Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
Summary = "Hot" };

// Serialize using TypeInfo<TValue> provided by the context
// and options specified by [JsonSourceGenerationOptions].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<StartupObject>SystemTextJsonSamples.Program</StartupObject>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
22 changes: 10 additions & 12 deletions docs/standard/serialization/system-text-json/source-generation.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: How to use source generation in System.Text.Json
description: "Learn how to use source generation in System.Text.Json."
ms.date: 10/09/2023
ms.date: 11/13/2025
no-loc: [System.Text.Json]
dev_langs:
- "csharp"
Expand All @@ -15,7 +15,7 @@ ms.topic: how-to

# How to use source generation in System.Text.Json

Source generation in System.Text.Json is available in .NET 6 and later versions. When used in an app, the app's language version must be C# 9.0 or later. This article shows you how to use source-generation-backed serialization in your apps.
This article shows you how to use source-generation-backed System.Text.Json serialization in your apps.

For information about the different source-generation modes, see [Source-generation modes](source-generation-modes.md).

Expand All @@ -29,23 +29,23 @@ To use source generation with all defaults (both modes, default options):

- Takes a <xref:System.Text.Json.Serialization.Metadata.JsonTypeInfo%601> 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 (.NET 7 and later only).
- 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.

By default, both source generation modes 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.
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.

Here's the type that is used in the following examples:
Here's the type that's used in the following examples:

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

Here's the context class configured to do source generation for the preceding `WeatherForecast` class:
Here's the context class configured to generate source for the preceding `WeatherForecast` class:

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

The types of `WeatherForecast` members don't need to be explicitly specified with `[JsonSerializable]` attributes. Members declared as `object` are an exception to this rule. The runtime type for a member declared as `object` needs to be specified. For example, suppose you have the following class:

:::code language="csharp" source="snippets/source-generation/csharp/ObjectProperties.cs" id="WF":::

And you know that at runtime it may have `boolean` and `int` objects:
And you know that at run time it might have `boolean` and `int` objects:

:::code language="csharp" source="snippets/source-generation/csharp/ObjectProperties.cs" id="WFInit":::

Expand Down Expand Up @@ -95,7 +95,7 @@ Here are the preceding examples in a complete program:

## Specify source-generation mode

You can specify metadata-based mode or serialization-optimization mode for an entire context, which may include multiple types. Or you can specify the mode for an individual type. If you do both, the mode specification for a type wins.
You can specify metadata-based mode or serialization-optimization mode for an entire context, which might include multiple types. Or you can specify the mode for an individual type. If you do both, the mode specification for a type wins.

- For an entire context, use the <xref:System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute.GenerationMode?displayProperty=nameWithType> property.
- For an individual type, use the <xref:System.Text.Json.Serialization.JsonSerializableAttribute.GenerationMode?displayProperty=nameWithType> property.
Expand Down Expand Up @@ -161,9 +161,7 @@ services.AddControllers().AddJsonOptions(
```

> [!NOTE]
> <xref:System.Text.Json.Serialization.JsonSourceGenerationMode.Serialization?displayProperty=nameWithType>, or fast-path serialization, isn't supported for asynchronous serialization.
>
> In .NET 7 and earlier versions, this limitation also applies to synchronous overloads of <xref:System.Text.Json.JsonSerializer.Serialize%2A?displayProperty=nameWithType> that accept a <xref:System.IO.Stream>. Starting with .NET 8, even though streaming serialization requires metadata-based models, it will fall back to fast-path if the payloads are known to be small enough to fit in the predetermined buffer size. For more information, see <https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#json>.
> <xref:System.Text.Json.Serialization.JsonSourceGenerationMode.Serialization?displayProperty=nameWithType>, or *fast-path* serialization, isn't supported for asynchronous serialization. Even though streaming serialization requires metadata-based models, it falls back to fast-path if the payloads are known to be small enough to fit in the predetermined buffer size. For more information, see <https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#json>.

## Disable reflection defaults

Expand Down Expand Up @@ -218,7 +216,7 @@ If you call a method that lets you pass in your own instance of `Utf8JsonWriter`

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`.

Here are the preceding examples in a complete program:
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
Loading