Reflexion im Vergleich zur Quellgenerierung in System.Text.Json

In diesem Artikel werden die Unterschiede zwischen der Reflexion und der Quellgenerierung im Zusammenhang mit der System.Text.Json-Serialisierung erläutert. Außerdem enthält er Anleitungen zum Auswählen des besten Ansatzes für Ihr Szenario.

Metadatensammlung

Zum Serialisieren oder Deserialisieren eines Typs benötigt JsonSerializer Informationen zur Vorgehensweise beim Zugriff auf die Member des Typs. JsonSerializer benötigt folgende Informationen:

  • Vorgehensweise beim Zugriff auf Eigenschaftengetter und Felder für die Serialisierung.
  • Vorgehensweise beim Zugriff auf einen Konstruktor, Eigenschaftensetter und Felder für die Deserialisierung.
  • Informationen darüber, welche Attribute zum Anpassen der Serialisierung oder Deserialisierung verwendet wurden.
  • Laufzeitkonfiguration von JsonSerializerOptions.

Diese Informationen werden als Metadaten bezeichnet.

Spiegelung

Standardmäßig erfasst JsonSerializer zur Laufzeit Metadaten mithilfe von Reflection. Wenn JsonSerializer zum ersten Mal einen Typen serialisieren oder deserialisieren muss, werden diese Metadaten erfasst und zwischengespeichert. Der Prozess der Metadatensammlung nimmt Zeit und Arbeitsspeicher in Anspruch.

Quellengenerierung

Alternativ kann System.Text.Json das C#-Feature zur Quellgenerierung verwenden, um die Leistung zu verbessern, die Nutzung des privaten Arbeitsspeichers zu reduzieren und das Kürzen von Assemblys zu erleichtern, wodurch die App-Größe reduziert wird. Darüber hinaus können bestimmte Reflexions-APIs nicht in nativen AOT-Anwendungen verwendet werden, daher müssen Sie die Quellgenerierung für diese Apps verwenden.

Es stehen ihnen zwei Quellgenerierungmodi zur Vefügung:

  • Metadatenbasierter Modus

    Während der Kompilierung sammelt System.Text.Json die für die Serialisierung erforderlichen Informationen und generiert Quellcodedateien, die JSON-Vertragsmetadaten für die angeforderten Typen auffüllen.

  • Serialisierungsoptimierungsmodus (schneller Pfad)

    JsonSerializer-Funktionen, die die Ausgabe der Serialisierung anpassen, z. B. Benennungsrichtlinien und Referenzerhaltung, verursachen einen Leistungsaufwand. Im Serialisierungsoptimierungsmodus generiert System.Text.Json optimierten Serialisierungscode, der direkt Utf8JsonWriter verwendet. Dieser optimierte oder Schnellpfad-Code erhöht den Serialisierungsdurchsatz.

    Die Deserialisierung mit schnellem Pfad ist derzeit nicht verfügbar. Weitere Informationen finden Sie unter dotnet/runtime issue 55043.

Die Quellgenerierung für System.Text.Json benötigt C# 9.0 oder höher.

Note

F#-Diskriminierte Union-Unterstützung funktioniert nur im Spiegelungsmodus. Es erfordert dynamischen Code und unbetrimmte Spiegelungsmetadaten. Sie können es nicht mit der Quellengenerierung oder mit Native AOT einsetzen. Weitere Informationen finden Sie unter F# diskriminierte Gewerkschaften.

Funktionsvergleiche

Wählen Sie Reflexions- oder Quellgenerierungsmodi auf Basis der folgenden jeweiligen Vorteile aus:

Vorteil Spiegelung Quellengenerierung
(Metadatenbasierter Modus)
Quellengenerierung
(Serialisierungsoptimierungsmodus)
Einfacher zu codieren. ✔️ ❌ ❌
Einfacher zu debuggen. ❌ ✔️ ✔️
Unterstützt [JsonInclude] für nicht öffentliche Mitglieder. ✔️ ✔️* ✔️*
Unterstützt alle verfügbaren Serialisierungsanpassungen. ✔️ ❌ † ❌ †
Reduziert die Startzeit. ❌ ✔️ ✔️
Reduziert die Auslastung des privaten Arbeitsspeichers. ❌ ✔️ ✔️
Entfernt laufzeitreflektion. ❌ ✔️ ✔️
Erleichtert die sichere Reduzierung der App-Größe. ❌ ✔️ ✔️
Erhöht den Serialisierungsdurchsatz. ❌ ❌ ✔️

* Ab .NET 11 unterstützt die Quellgenerierung private, internal und protected-Member, die Sie explizit mit [JsonInclude] markieren. Es unterstützt auch private, internal und protected Accessoren für Eigenschaften, die Sie mit [JsonInclude] kennzeichnen. Die metadatenbasierte Quellgenerierung unterstützt nicht zugängliche Konstruktoren, die Sie mit [JsonConstructor] markieren. Generierte Setter werden nur für init"-only"-Eigenschaften ausgeführt, die im JSON-Code angezeigt werden, sodass ausgelassene Eigenschaften ihre Initialisierungswerte beibehalten. In .NET 10 und früheren Versionen unterstützt die Quellgenerierung keine private- oder protected-Member bzw. -Accessoren und auch keine nicht zugänglichen Konstruktoren. Der generierte Kontext kann nur dann auf Member und Accessoren zugreifen internal , wenn sie eine Assembly freigeben. Weitere Informationen finden Sie unter Nicht öffentliche Member und Konstruktoren. † Verwenden sie die Vertragsanpassungs-API, um vom Quell generierte Verträge zu ändern.