この記事では、System.Text.Json シリアル化に関連するリフレクションとソース生成の相違点について説明します。 また、シナリオに最適な方法を選択する方法に関するガイダンスも示します。
メタデータ収集
型をシリアル化または逆シリアル化するには、JsonSerializer に、型のメンバーにアクセスする方法に関する情報が必要です。
JsonSerializer では次の情報が必要です。
- シリアル化のためにプロパティのゲッターとフィールドにアクセスする方法。
- 逆シリアル化用として、コンストラクター、プロパティセッター、およびフィールドにアクセスする方法。
- シリアル化または逆シリアル化をカスタマイズするために使用されている属性の情報。
- JsonSerializerOptionsからのランタイム構成。
この情報は "メタデータ" と呼ばれます。
リフレクション
既定では、 JsonSerializer は リフレクションを使用して実行時にメタデータを収集します。
JsonSerializer で初めて型をシリアル化または逆シリアル化する必要がある場合は、常に、このメタデータを収集してキャッシュします。 メタデータのコレクション プロセスには時間がかかり、メモリが使用されます。
ソース生成
別の方法として、System.Text.Json では、C# のソース生成機能を使用して、パフォーマンスを向上させ、プライベート メモリの使用量を削減し、アセンブリのトリミングを容易にすることができます。これにより、アプリのサイズが小さくなります。 さらに、特定のリフレクション API はネイティブ AOT アプリケーションでは使用できないため、これらのアプリにはソース生成を使用する必要があります。
ソース生成は、次の 2 つのモードで使用できます。
メタデータベースのモード
コンパイル時に、
System.Text.Jsonはシリアル化に必要な情報を収集し、要求された型の JSON コントラクト メタデータを設定するソース コード ファイルを生成します。シリアル化の最適化 (高速パス) モード
命名ポリシーや参照保持など、シリアル化の出力をカスタマイズする JsonSerializer 機能は、パフォーマンスのオーバーヘッドを伴います。 シリアル化最適化モードでは、System.Text.Json は
Utf8JsonWriterを直接使用する最適化されたシリアル化コードを生成します。 この最適化されたコードまたは高速パス コードにより、シリアル化のスループットが向上します。現在、高速パスの逆シリアル化は使用できません。 詳細については、dotnet/runtime issue 55043 を参照してください。
System.Text.Json のソースの生成には、C# 9.0 以降のバージョンが必要です。
Note
F# の判別共用体は、リフレクション モードでのみサポートされます。 動的なコードと未作成のリフレクション メタデータが必要です。 ソース生成またはネイティブ AOT では使用できません。 詳細については、「 F# 判別共用体」を参照してください。
機能の比較
それぞれがもたらす特長に基づいて、リフレクションまたはソース生成モードを選択してください。
| 利点 | リフレクション | ソース生成 (メタデータベースのモード) |
ソース生成 (シリアル化の最適化モード) |
|---|---|---|---|
| コードが簡単になります。 | ✔️ | ❌ | ❌ |
| デバッグが簡単になります。 | ❌ | ✔️ | ✔️ |
非パブリック メンバーの [JsonInclude] をサポートします。 |
✔️ | ✔️* | ✔️* |
| 使用可能なシリアル化のカスタマイズをすべてサポートします。 | ✔️ | ❌ † | ❌ † |
| 起動時間が短縮します。 | ❌ | ✔️ | ✔️ |
| プライベート メモリの使用量が削減されます。 | ❌ | ✔️ | ✔️ |
| ランタイムリフレクションを排除します。 | ❌ | ✔️ | ✔️ |
| トリミングセーフなアプリ サイズの縮小が容易になります。 | ❌ | ✔️ | ✔️ |
| シリアル化のスループットが向上します。 | ❌ | ❌ | ✔️ |
* .NET 11 以降では、ソース生成では、[JsonInclude] で明示的にマークしたprivate、internal、およびprotectedメンバーがサポートされます。 また、[JsonInclude]でマークするプロパティのprivate、internal、およびprotectedアクセサーもサポートします。 メタデータベースのソース生成では、[ JsonConstructor] でマークしたアクセスできないコンストラクターがサポートされます。 生成されたセッターは、JSON に表示される initのみのプロパティに対してのみ実行されるため、省略されたプロパティは初期化子の値を保持します。 .NET 10 以前のバージョンでは、ソース生成では、privateまたはprotectedメンバーまたはアクセサー、またはアクセスできないコンストラクターはサポートされていません。 生成されたコンテキストは、アセンブリ internal 共有する場合にのみ、メンバーとアクセサーにアクセスできます。 詳細については、「 非パブリック メンバーとコンストラクター」を参照してください。
† コントラクトカスタマイズ API を使用して、ソースで生成されたコントラクトを変更します。
.NET