System.Text.Json におけるリフレクションとソース生成
この記事では、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 以降のバージョンが必要です。
機能の比較
それぞれがもたらす特長に基づいて、リフレクションまたはソース生成モードを選択してください。
特長 | リフレクション | ソース生成 (メタデータベースのモード) |
ソース生成 (シリアル化の最適化モード) |
---|---|---|---|
コードが簡単になります。 | ✔️ | ❌ | ❌ |
デバッグが簡単になります。 | ❌ | ✔️ | ✔️ |
非パブリック メンバーをサポートします。 | ✔️ | ✔️ | ✔️ |
使用可能なシリアル化のカスタマイズをすべてサポートします。 | ✔️ | ||
起動時間が短縮します。 | ❌ | ✔️ | ✔️ |
プライベート メモリの使用量が削減されます。 | ❌ | ✔️ | ✔️ |
実行時のリフレクションが不要になります。 | ❌ | ✔️ | ✔️ |
トリミングセーフなアプリ サイズの縮小が容易になります。 | ❌ | ✔️ | ✔️ |
シリアル化のスループットが向上します。 | ❌ | ❌ | ✔️ |
* ソース ジェネレーターは、一部の非パブリック メンバー (たとえば、同じアセンブリ内の内部型) をサポートします。 † ソース生成コントラクトは、コントラクト カスタマイズ API を使用して変更できます。
.NET