Quellgenerierungsmodi in System.Text.Json

Die Quellgenerierung kann in zwei Modi verwendet werden: Metadatenbasierte und Serialisierungsoptimierung. In diesem Artikel werden die verschiedenen Modi beschrieben.

Informationen zur Verwendung von Quellgenerierungsmodi finden Sie unter Verwenden der Quellgenerierung in System.Text.Json.

Metadatenbasierter Modus

Sie können die Quellgenerierung verwenden, um den Metadatensammlungsprozess von Laufzeit zu Kompilierungszeit zu verschieben. Während der Kompilierung werden die Metadaten gesammelt und Quellcodedateien generiert. Die generierten Quellcodedateien werden automatisch als integraler Bestandteil der Anwendung kompiliert. Diese Technik beseitigt die Laufzeitmetadatensammlung, wodurch die Leistung sowohl der Serialisierung als auch der Deserialisierung verbessert wird.

Die aus der Quellgenerierung resultierenden Leistungsverbesserungen können erheblich sein. Die Testergebnisse haben beispielsweise eine Reduzierung der Startzeit um bis zu 40 % oder mehr, eine Verringerung des privaten Arbeitsspeichers, eine Erhöhung der Durchsatzgeschwindigkeit (im Serialisierungsoptimierungsmodus) und eine Verringerung der App-Größe gezeigt.

Nicht öffentliche Mitglieder und Konstruktoren

Standardmäßig enthalten sowohl der Spiegelungsmodus als auch der Quellgenerierungsmodus nur public Eigenschaften und Felder im Serialisierungsvertrag.

Ab .NET 11 unterstützt die Quellgenerierung Member, die Sie explizit mit dem Attribut [JsonInclude] markieren. Das Element kann private, internal oder protected sein. Es unterstützt auch private, internal und protected Accessoren für Eigenschaften, die Sie mit [JsonInclude] kennzeichnen. Die Quellgenerierung unterstützt auch nicht zugängliche Konstruktoren, die mit [JsonConstructor] gekennzeichnet sind.

Unter .NET 11 verwenden die generierten Accessoren UnsafeAccessorAttribute.

Ein vom Quell generierter Setter für eine reine init Eigenschaft wird nur ausgeführt, wenn die JSON-Payload diese Eigenschaft enthält. Eine reine init Eigenschaft, die von der Nutzlast weggelassen wird, behält den Wert vom Eigenschaftsinitialisierer bei.

In .NET 10 und früheren Versionen hat die Quellgenerierung die folgenden Einschränkungen:

  • Die Quellgenerierung unterstützt weder private-Member noch protected-Zugriffsmethoden. Wenn Sie ein solches Mitglied mit [JsonInclude] markieren, wirft der Serializer zur Laufzeit eine NotSupportedException.
  • Die Quellgenerierung unterstützt internal-Member und -Accessoren nur, wenn sie für die generierte JsonSerializerContext in derselben Assembly zugänglich sind.
  • Die Quellgenerierung unterstützt keine Konstruktoren, die nicht auf den generierten Kontext zugreifen können, auch wenn Sie sie mit [JsonConstructor]markiert haben.

Bekannte Probleme

Informationen zu anderen bekannten Problemen bei der Quellgenerierung finden Sie unter GitHub-Problemen mit dem Etikett „source-generator“ im dotnet/runtime-Repository.

Serialisierungsoptimierungsmodus (schneller Pfad)

JsonSerializer verfügt über viele Features, die die Ausgabe der Serialisierung anpassen, z. B. Schreibweise für alle Eigenschaftsnamen und Beibehalten von Verweisen. Die Unterstützung all dieser Features verursacht einen gewissen Leistungsaufwand. Die Quellgenerierung kann die Serialisierungsleistung verbessern, indem optimierter Code generiert wird, der Utf8JsonWriter direkt verwendet.

Der Serialisierungsoptimierungsmodus gibt methoden für die Serialisierung schneller Pfade aus, aber keine Serialisierungsmetadaten. Die Fast-Path-Serialisierung ist in ihrer Funktionsweise eingeschränkt; sie unterstützt keine asynchrone Serialisierung oder irgendeinen Modus der Deserialisierung.

Darüber hinaus unterstützt der optimierte Code nicht alle Serialisierungsfunktionen, die JsonSerializer unterstützt. Das Serialisierungsmodul erkennt, ob der optimierte Code verwendet werden kann, und greift auf den Standardserialisierungscode zurück, wenn nicht unterstützte Optionen angegeben werden. Beispielsweise ist JsonNumberHandling.AllowReadingFromString nicht auf das Schreiben anwendbar, sodass die Angabe dieser Option nicht zu einem Rückgriff auf den Standardcode führt.

Die folgende Tabelle zeigt, welche Optionen in JsonSerializerOptions von der Serialisierung mit schnellem Pfad unterstützt werden:

Serialisierungsoption Unterstützt für Fast-Path
AllowTrailingCommas ✔️
Converters ❌
DefaultBufferSize ✔️
DefaultIgnoreCondition ✔️
DictionaryKeyPolicy ❌
Encoder ❌
IgnoreNullValues ❌
IgnoreReadOnlyFields ✔️
IgnoreReadOnlyProperties ✔️
IncludeFields ✔️
MaxDepth ✔️
NumberHandling ❌
PropertyNamingPolicy ✔️
ReferenceHandler ❌
TypeInfoResolver ✔️
WriteIndented ✔️

(Die folgenden Optionen werden nicht unterstützt, da sie nur für die Deserialisierung gelten: PropertyNameCaseInsensitive, ReadCommentHandlingund UnknownTypeHandling.)

Die folgende Tabelle zeigt, welche Attribute durch die Serialisierung mit schnellem Pfad unterstützt werden:

Attribut Unterstützt für Fast-Path
JsonConstructorAttribute ❌
JsonConverterAttribute ❌
JsonDerivedTypeAttribute ✔️
JsonExtensionDataAttribute ❌
JsonIgnoreAttribute ✔️
JsonIncludeAttribute ✔️
JsonNumberHandlingAttribute ❌
JsonPolymorphicAttribute ✔️
JsonPropertyNameAttribute ✔️
JsonPropertyOrderAttribute ✔️
JsonRequiredAttribute ✔️

Wenn eine nicht unterstützte Option oder ein Attribut für einen Typ angegeben wird, greift der Serializer auf den Metadatenmodus zurück, vorausgesetzt, der Quellgenerator wurde zum Generieren von Metadaten konfiguriert. In diesem Fall wird der optimierte Code beim Serialisieren dieses Typs nicht verwendet, kann jedoch für andere Typen verwendet werden. Daher ist es wichtig, Leistungstests mit Ihren Optionen und Workloads durchzuführen, um zu ermitteln, wie viel Nutzen Sie tatsächlich aus dem Serialisierungsoptimierungsmodus ziehen können. Außerdem erfordert die Möglichkeit, auf JsonSerializer Code zurückzugreifen, den Metadatenmodus. Wenn Sie nur den Serialisierungsoptimierungsmodus auswählen, tritt bei der Serialisierung möglicherweise für Typen oder Optionen, die auf JsonSerializer-Code zurückgreifen müssen, ein Fehler auf.

Siehe auch