Migrieren von Newtonsoft.Json zu System.Text.Json
In diesem Artikel wird erläutert, wie Sie von Newtonsoft.Json zu System.Text.Json migrieren.
Der System.Text.Json
-Namespace bietet Funktionalitäten zum Serialisieren in und Deserialisieren aus JSON (JavaScript Object Notation). Die Bibliothek System.Text.Json
ist ab .NET Core 3.1 in der Runtime enthalten. Installieren Sie für andere Zielframeworks das NuGet-Paket System.Text.Json. Das Paket unterstützt:
- .NET Standard 2.0 und höhere Versionen
- .NET Framework 4.6.2 und höhere Versionen
- .NET Core 2.0, 2.1 und 2.2
Tipp
Sie können KI-Unterstützung verwenden, um von Newtonsoft.Json
mit GitHub Copilot zu migrieren.
System.Text.Json
konzentriert sich hauptsächlich auf Leistung, Sicherheit und Einhaltung von Standards. Es weist einige wesentliche Unterschiede beim Standardverhalten auf und zielt nicht auf Featureparität mit Newtonsoft.Json
ab. In einigen Szenarios verfügt System.Text.Json
aktuell über keine integrierte Funktionalität, doch gibt es dafür empfohlene Problemumgehungen. In anderen Szenarien sind Problemumgehungen nicht praktikabel.
Das System.Text.Json
-Team investiert in das Hinzufügen der Features, die am häufigsten angefordert werden. Wenn Ihre Anwendung von einem fehlenden Feature abhängig ist, sollten Sie erwägen, im GitHub-Repository „dotnet/runtime“ ein Issue zu registrieren, um herauszufinden, ob eine Unterstützung für Ihr Szenario hinzugefügt werden kann.
Der Großteil dieses Artikels behandelt die Verwendungsweise der JsonSerializer-API, aber er enthält auch Anleitungen zur Verwendung der Typen JsonDocument (der das Dokumentobjektmodell (DOM) darstellt), Utf8JsonReader und Utf8JsonWriter.
In Visual Basic können Sie Utf8JsonReader nicht verwenden, was auch bedeutet, dass Sie keine benutzerdefinierten Konverter schreiben können. Für die meisten der hier vorgestellten Problemumgehungen müssen Sie benutzerdefinierte Konverter schreiben. Sie können einen benutzerdefinierten Konverter in C# schreiben und in einem Visual Basic-Projekt registrieren. Weitere Informationen finden Sie unter Visual Basic-Support.
Übersicht über die Unterschiede
In der folgenden Tabelle sind die Newtonsoft.Json
-Funktionen mit ihren Entsprechungen in System.Text.Json
aufgeführt. Die Entsprechungen lassen sich in die folgenden Kategorien einteilen:
- ✔️ Unterstützt durch integrierte Funktionalität Um ein ähnliches Verhalten von
System.Text.Json
zu erzielen, ist möglicherweise die Verwendung eines Attributs oder einer globalen Option erforderlich. - ⚠️ Nicht unterstützt, Problemumgehung ist möglich. Die Problemumgehungen sind benutzerdefinierte Konverter, die möglicherweise keine vollständige Parität mit der
Newtonsoft.Json
-Funktionalität bereitstellen. Für einige davon wird Beispielcode als Beispiele bereitgestellt. Wenn Sie von diesenNewtonsoft.Json
-Funktionen abhängig sind, erfordert die Migration Änderungen an Ihren .NET-Objektmodellen oder andere Codeänderungen. - ❌ Nicht unterstützt, Problemumgehung ist nicht praktikabel oder nicht möglich Wenn Sie von diesen
Newtonsoft.Json
-Funktionen abhängig sind, ist die Migration nicht ohne wesentliche Änderungen möglich.
Feature in Newtonsoft.Json | Äquivalent in System.Text.Json |
---|---|
Standardmäßige Deserialisierung ohne Berücksichtigung von Groß-/Kleinschreibung | ✔️ Globale Einstellung „PropertyNameCaseInsensitive“ |
Eigenschaftsnamen mit Camel-Case-Schreibweise | ✔️ Globale Einstellung „PropertyNamingPolicy“ |
Eigenschaftsnamen mit Snake-Case-Schreibweise | ✔️ Snake-Case-Benennungsrichtlinie |
Minimales Escapen von Zeichen | ✔️ Strenges Escapen von Zeichen, konfigurierbar |
Globale Einstellung NullValueHandling.Ignore |
✔️ DefaultIgnoreCondition (globale Option) |
Kommentare zulassen | ✔️ Globale Einstellung „ReadCommentHandling“ |
Nachfolgende Kommas zulassen | ✔️ Globale Einstellung „AllowTrailingCommas“ |
Registrierung benutzerdefinierter Konverter | ✔️ Rangordnung weicht ab |
Standardmäßige maximale Tiefe von 64, konfigurierbar | ✔️ Standardmäßige maximale Tiefe von 64, konfigurierbar |
Globale Einstellung PreserveReferencesHandling |
✔️ ReferenceHandling (globale Einstellung) |
Serialisieren oder Deserialisieren von Zahlen in Anführungszeichen | ✔️ NumberHandling (globale Einstellung), [JsonNumberHandling] (Attribut) |
Deserialisieren in unveränderliche Klassen und Strukturen | ✔️ JsonConstructor, C# 9-Datensätze |
Unterstützung für Felder | ✔️ IncludeFields (globale Einstellung), [JsonInclude] (Attribut) |
Globale Einstellung DefaultValueHandling |
✔️ DefaultIgnoreCondition (globale Einstellung) |
Einstellung NullValueHandling für [JsonProperty] |
✔️ JsonIgnore (Attribut) |
Einstellung DefaultValueHandling für [JsonProperty] |
✔️ JsonIgnore (Attribut) |
Deserialisieren von Dictionary mit Nicht-Zeichenfolgen-Schlüssel |
✔️ Unterstützt |
Unterstützung für nicht öffentliche Setter und Getter von Eigenschaften | ✔️ JsonInclude (Attribut) |
[JsonConstructor] -Attribut |
✔️ [JsonConstructor] (Attribut) |
Globale Einstellung ReferenceLoopHandling |
✔️ ReferenceHandling (globale Einstellung) |
Rückrufe | ✔️ Rückrufe |
„NaN“, „Infinity“, „-Infinity“ | ✔️ Unterstützt |
Required -Einstellung für [JsonProperty] -Attribut |
✔️ [JsonRequired]-Attribut und erforderlicher C#-Modifizierer |
DefaultContractResolver zum Ignorieren von Eigenschaften |
✔️ „DefaultJsonTypeInfoResolver“-Klasse |
Polymorphe Serialisierung | ✔️ [JsonDerivedType]-Attribut |
Polymorphe Deserialisierung | ✔️ Typdiskriminator für das [JsonDerivedType]-Attribut |
Deserialisieren des Enumerationswerts für Zeichenfolgen | ✔️ Deserialisieren von Enumerationswerten für Zeichenfolgen |
Globale Einstellung MissingMemberHandling |
✔️ Behandeln fehlender Member |
Auffüllen von Eigenschaften ohne Setter | ✔️ Auffüllen von Eigenschaften ohne Setter |
Globale Einstellung ObjectCreationHandling |
✔️ Wiederverwenden statt Ersetzen von Eigenschaften |
Unterstützung für ein breites Spektrum von Typen | ⚠️ Einige Typen benötigen benutzerdefinierte Konverter |
Deserialisieren eines abgeleiteten Typs in object -Eigenschaften |
⚠️ Nicht unterstützt, Problemumgehung, Beispiel |
Deserialisieren des JSON-Literals null in Non-Nullable-Werttypen |
⚠️ Nicht unterstützt, Problemumgehung, Beispiel |
Einstellungen DateTimeZoneHandling und DateFormatString |
⚠️ Nicht unterstützt, Problemumgehung, Beispiel |
JsonConvert.PopulateObject -Methode |
⚠️ Nicht unterstützt, Problemumgehung, Beispiel |
Unterstützung für System.Runtime.Serialization -Attribute |
⚠️ Nicht unterstützt, Problemumgehung, Beispiel |
JsonObjectAttribute |
⚠️ Nicht unterstützt, Problemumgehung, Beispiel |
Eigenschaftsnamen ohne Anführungszeichen zulassen | ❌Vom Design nicht unterstützt |
Einschließen von Zeichenfolgenwerten in einfache Anführungszeichen zulassen | ❌Vom Design nicht unterstützt |
JSON-Werte, die keine Zeichenfolgen sind, für Zeichenfolgeneigenschaften zulassen | ❌Vom Design nicht unterstützt |
Globale Einstellung TypeNameHandling.All |
❌Vom Design nicht unterstützt |
Unterstützung für JsonPath -Abfragen |
❌Nicht unterstützt |
Konfigurierbare Grenzwerte | ❌Nicht unterstützt |
Dies ist keine vollständige Liste der Newtonsoft.Json
-Funktionen. Die Liste enthält viele der Szenarien, die in GitHub-Issues oder StackOverflow-Beiträgen angefordert wurden. Wenn Sie eine Problemumgehung für eins der hier aufgelisteten Szenarien implementieren, für das derzeit kein Beispielcode vorhanden ist, und wenn Sie Ihre Lösung teilen möchten, wählen Sie Diese Seite im Abschnitt Feedback unten auf dieser Seite aus. Dadurch wird ein Issue im GitHub-Repository dieser Dokumentation erstellt und dieses ebenfalls im Abschnitt Feedback auf dieser Seite aufgeführt.
Unterschiede beim Standardverhalten
System.Text.Json ist standardmäßig strikt und vermeidet jegliche Vermutung oder Interpretation im Namen des Aufrufers, womit deterministisches Verhalten betont wird. Die Bibliothek ist absichtlich auf diese Weise für Leistung und Sicherheit konzipiert. Newtonsoft.Json
ist standardmäßig flexibel. Dieser grundlegende Unterschied beim Design steht hinter vielen der folgenden spezifischen Unterschiede im Standardverhalten.
Deserialisierung ohne Berücksichtigung von Groß-/Kleinschreibung
Während der Deserialisierung führt Newtonsoft.Json
standardmäßig einen Abgleich der Eigenschaftsnamen ohne Berücksichtigung von Groß-/Kleinschreibung durch. Das Standardverhalten von System.Text.Json berücksichtigt die Groß-/Kleinschreibung, was eine bessere Leistung liefert, weil ein exakter Abgleich erfolgt. Informationen, wie Sie einen Abgleich ohne Berücksichtigung von Groß-/Kleinschreibung durchführen, finden Sie unter Eigenschaftenabgleich ohne Berücksichtigung von Groß-/Kleinschreibung.
Wenn Sie System.Text.Json
indirekt durch Verwendung von ASP.NET Core verwenden, müssen Sie nichts tun, um ein Verhalten wie Newtonsoft.Json
zu erhalten. ASP.NET Core gibt die Einstellungen für die Verwendung von Eigenschaftsnamen mit Camel-Case-Schreibweise an sowie für den Abgleich ohne Berücksichtigung von Groß-/Kleinschreibung, wenn System.Text.Json
verwendet wird.
ASP.NET Core ermöglicht auch standardmäßig das Deserialisieren von Zahlen in Anführungszeichen.
Minimales Escapen von Zeichen
Während der Serialisierung ist Newtonsoft.Json
relativ nachsichtig, wenn es um das Durchlassen von Zeichen geht, ohne sie zu escapen. Dies bedeutet, dass sie nicht durch \uxxxx
ersetzt werden, wobei xxxx
der Codepunkt des Zeichens ist. Wenn sie escapet werden, geschieht dies durch Ausgabe eines umgekehrten Schrägstrichs (\
) vor dem Zeichen (z. B. wird "
zu \"
). System.Text.Json escapet standardmäßig mehr Zeichen, um eine tief greifenden Abwehr als Schutz vor Cross-Site Scripting (XSS)- oder Information-Disclosure-Angriffen (Veröffentlichung von Informationen) zu bieten, wobei dies durch Verwendung der Abfolge von sechs Zeichen erzielt wird. System.Text.Json
escapet standardmäßig alle Nicht-ASCII-Zeichen, sodass Sie nichts machen müssen, wenn Sie StringEscapeHandling.EscapeNonAscii
in Newtonsoft.Json
verwenden. System.Text.Json
escapet außerdem standardmäßig HTML-abhängige Zeichen. Informationen, wie Sie das Standardverhalten von System.Text.Json
außer Kraft setzen können, finden Sie unter Anpassen der Zeichencodierung.
Kommentare
Während der Deserialisierung ignoriert Newtonsoft.Json
standardmäßig Kommentare in der JSON-Datei. Das Standardverhalten von System.Text.Json besteht im Auslösen von Ausnahmen für Kommentare, weil die Spezifikation RFC 8259 diese nicht umfasst. Informationen, wie Sie Kommentare zulassen können, finden Sie unter Zulassen von Kommentaren und nachfolgenden Kommas.
Nachfolgende Kommas
Während der Deserialisierung ignoriert Newtonsoft.Json
standardmäßig nachfolgende Kommas. Es ignoriert ferner mehrere nachfolgende Kommas (z. B. [{"Color":"Red"},{"Color":"Green"},,]
). Das Standardverhalten von System.Text.Json besteht im Auslösen von Ausnahmen für nachfolgende Kommas, weil die Spezifikation RFC 8259 diese nicht zulässt. Informationen, wie Sie System.Text.Json
dazu bringen, diese zu akzeptieren, finden Sie unter Zulassen von Kommentaren und nachfolgenden Kommas. Es gibt keine Möglichkeit, mehrere nachfolgende Kommas zuzulassen.
Rangfolge für die Registrierung von Konvertern
Die Rangfolge der Registrierung von benutzerdefinierten Konvertern in Newtonsoft.Json
ist wie folgt:
- Attribut auf Eigenschaftsebene
- Attribut auf Typebene
- Converters-Sammlung
Diese Reihenfolge bedeutet, dass ein benutzerdefinierter Konverter in der Converters
-Sammlung von einem Konverter außer Kraft gesetzt wird, der durch Anwenden eines Attributs auf Typebene registriert wird. Beide dieser Registrierungen werden von einem Attribut auf Eigenschaftsebene außer Kraft gesetzt.
Die Rangfolge der Registrierung von benutzerdefinierten Konvertern in System.Text.Json weicht hiervon ab:
- Attribut auf Eigenschaftsebene
- Converters-Sammlung
- Attribut auf Typebene
Der Unterschied besteht hierbei darin, dass ein benutzerdefinierter Konverter in der Converters
-Sammlung ein Attribut auf Typebene außer Kraft setzt. Die Absicht hinter dieser Rangfolge ist es, dass Änderungen zur Laufzeit eine zur Entwurfszeit getroffene Auswahl außer Kraft setzen sollen. Diese Rangfolge lässt sich nicht ändern.
Weitere Informationen zur Registrierung benutzerdefinierter Konverter finden Sie unter Registrieren eines benutzerdefinierten Konverters.
Maximale Tiefe
Die neueste Version von Newtonsoft.Json
weist standardmäßig einen Grenzwert von 64 für die maximale Tiefe auf. System.Text.Json verfügt ebenfalls über einen Standardgrenzwert von 64, der sich durch Festlegen von JsonSerializerOptions.MaxDepth konfigurieren lässt.
Wenn Sie System.Text.Json
indirekt durch ASP.NET Core verwenden, beträgt die Obergrenze für die maximale Tiefe standardmäßig 32. Der Standardwert ist der gleiche wie bei Modellbindung und wird in der JsonOptions-Klasse festgelegt.
JSON-Zeichenfolgen (Eigenschaftsnamen und Zeichenfolgenwerte)
Während der Deserialisierung akzeptiert Newtonsoft.Json
Eigenschaftsnamen, die in doppelten oder einfachen Anführungszeichen stehen oder gar keine Anführungszeichen aufweisen. Es akzeptiert Zeichenfolgenwerte, die in doppelten oder einfachen Anführungszeichen stehen. Newtonsoft.Json
akzeptiert beispielsweise folgendes JSON:
{
"name1": "value",
'name2': "value",
name3: 'value'
}
System.Text.Json
akzeptiert nur Eigenschaftsnamen und Zeichenfolgenwerte, die in doppelten Anführungszeichen stehen, weil dieses Format von der Spezifikation RFC 8259 gefordert wird und das einzige Format ist, das als gültiges JSON-Format gilt.
Ein in einfache Anführungszeichen eingeschlossener Wert führt zu einer JsonException mit folgender Meldung:
''' is an invalid start of a value.
Werte, die keine Zeichenfolgen sind, für Zeichenfolgeneigenschaften
Newtonsoft.Json
akzeptiert Werte, die keine Zeichenfolgen sind, z. B. eine Zahl oder die Literale true
und false
, für die Deserialisierung von Eigenschaften vom Typ „String“ (Zeichenfolge). Im Folgenden finden Sie ein JSON-Beispiel, das Newtonsoft.Json
erfolgreich in die folgende Klasse deserialisiert:
{
"String1": 1,
"String2": true,
"String3": false
}
public class ExampleClass
{
public string String1 { get; set; }
public string String2 { get; set; }
public string String3 { get; set; }
}
System.Text.Json
deserialisiert Werte, die keine Zeichenfolgen sind, nicht in Zeichenfolgeneigenschaften. Ein für ein Zeichenfolgenfeld empfangener Wert, der keine Zeichenfolge ist, führt zu einer JsonException mit folgender Meldung:
The JSON value could not be converted to System.String.
Szenarien mit JsonSerializer
Einige der folgenden Szenarien werden von der integrierten Funktionalität nicht unterstützt, aber Problemumgehungen sind möglich. Die Problemumgehungen sind benutzerdefinierte Konverter, die möglicherweise keine vollständige Parität mit der Newtonsoft.Json
-Funktionalität bereitstellen. Für einige davon wird Beispielcode als Beispiele bereitgestellt. Wenn Sie von diesen Newtonsoft.Json
-Funktionen abhängig sind, erfordert die Migration Änderungen an Ihren .NET-Objektmodellen oder andere Codeänderungen.
Für einige der folgenden Szenarien sind Problemumgehungen nicht praktikabel oder möglich. Wenn Sie von diesen Newtonsoft.Json
-Funktionen abhängig sind, ist die Migration nicht ohne wesentliche Änderungen möglich.
Zulassen oder Schreiben von Zahlen in Anführungszeichen
Newtonsoft.Json
kann Zahlen serialisieren oder deserialisieren, die von JSON-Zeichenfolgen (in Anführungszeichen) dargestellt werden. Beispielsweise kann es {"DegreesCelsius":"23"}
akzeptieren, anstelle von {"DegreesCelsius":23}
. Um dieses Verhalten in System.Text.Json zu aktivieren, legen Sie JsonSerializerOptions.NumberHandling auf WriteAsString oder AllowReadingFromString fest, oder verwenden Sie das Attribut [JsonNumberHandling].
Wenn Sie System.Text.Json
indirekt durch Verwendung von ASP.NET Core verwenden, müssen Sie nichts tun, um ein Verhalten wie Newtonsoft.Json
zu erhalten. ASP.NET Core gibt Webstandardwerte an, wenn es System.Text.Json
verwendet, und Webstandardwerte erlauben Zahlen in Anführungszeichen.
Weitere Informationen finden Sie unter Zulassen oder Schreiben von Zahlen in Anführungszeichen.
Angeben des bei der Deserialisierung zu verwendenden Konstruktors
Mit dem Newtonsoft.Json
-Attribut von [JsonConstructor]
können Sie angeben, welcher Konstruktor beim Deserialisieren in ein POCO aufgerufen werden soll.
System.Text.Json
verfügt auch über das Attribut [JsonConstructor]. Weitere Informationen finden Sie unter Unveränderliche Typen und Datensätze.
Bedingtes Ignorieren einer Eigenschaft
Newtonsoft.Json
bietet mehrere Möglichkeiten, um eine Eigenschaft bei der Serialisierung oder Deserialisierung bedingt zu ignorieren:
DefaultContractResolver
ermöglicht das Auswählen von Eigenschaften, die basierend auf beliebigen Kriterien eingeschlossen oder ignoriert werden sollen.- Mit den Einstellungen
NullValueHandling
undDefaultValueHandling
vonJsonSerializerSettings
können Sie angeben, dass alle Eigenschaften mit Nullwert oder Standardwert ignoriert werden sollen. - Mit den Einstellungen
NullValueHandling
undDefaultValueHandling
des[JsonProperty]
-Attributs können Sie einzelne Eigenschaften angeben, die ignoriert werden sollen, wenn Sie auf Null oder den Standardwert festgelegt sind.
System.Text.Json bietet die folgenden Möglichkeiten, Eigenschaften oder Felder bei der Serialisierung zu ignorieren:
- Das [JsonIgnore]-Attribut einer Eigenschaft bewirkt, dass die Eigenschaft während der Serialisierung im JSON-Code ausgelassen wird.
- Mit der globalen Option IgnoreReadOnlyProperties können Sie alle schreibgeschützten Eigenschaften ignorieren.
- Wenn Sie Felder einschließen, können Sie mit der JsonSerializerOptions.IgnoreReadOnlyFields globalen Option alle schreibgeschützten Felder ignorieren.
- Mit der globalen Option
DefaultIgnoreCondition
können Sie alle Wertetypeigenschaften mit Standardwerten ignorieren oder alle Verweistypeigenschaften mit dem Wert NULL ignorieren.
Darüber hinaus können Sie in .NET 7 und höheren Versionen den JSON-Vertrag anpassen, um Eigenschaften basierend auf beliebigen Kriterien zu ignorieren. Weitere Informationen finden Sie unter Benutzerdefinierte Verträge.
Öffentliche und nicht öffentliche Felder
Newtonsoft.Json
kann Felder ebenso wie Eigenschaften serialisieren und deserialisieren.
Verwenden Sie in System.Text.Json die globale Einstellung JsonSerializerOptions.IncludeFields oder das Attribut [JsonInclude], um öffentliche Felder bei der Serialisierung oder Deserialisierung einzuschließen. Ein Beispiel finden Sie unter Einschließen von Feldern.
Erhalten von Objektverweise und Behandeln von Schleifen
Standardmäßig serialisiert Newtonsoft.Json
als Wert. Wenn ein Objekt beispielsweise zwei Eigenschaften enthält, die einen Verweis auf dasselbe Person
-Objekt enthalten, werden die Werte der Eigenschaften dieses Person
-Objekts in JSON dupliziert.
Newtonsoft.Json
verfügt über eine PreserveReferencesHandling
-Einstellung für JsonSerializerSettings
, mit der Sie als Verweis serialisieren können:
- Dem für das erste
Person
-Objekt erstellten JSON-Code werden Bezeichnermetadaten hinzugefügt. - Der für das zweite
Person
-Objekt erstellte JSON-Code enthält einen Verweis auf diesen Bezeichner anstelle der Eigenschaftswerte.
Newtonsoft.Json
verfügt außerdem über eine ReferenceLoopHandling
-Einstellung, mit der Sie Zirkelbezüge ignorieren können, anstatt eine Ausnahme auszulösen.
Um Verweise beizubehalten und Zirkelbezüge zu behandeln, legen Sie System.Text.Json in JsonSerializerOptions.ReferenceHandler auf Preserve fest. Die Einstellung ReferenceHandler.Preserve
entspricht PreserveReferencesHandling
= PreserveReferencesHandling.All
in Newtonsoft.Json
.
Die Option ReferenceHandler.IgnoreCycles
weist ein Verhalten ähnlich Newtonsoft.JsonReferenceLoopHandling.Ignore
auf. Ein Unterschied besteht darin, dass die System.Text.Json-Implementierung Verweisschleifen durch das JSON-Token null
ersetzt, anstatt den Objektverweis zu ignorieren. Weitere Informationen finden Sie unter Ignorieren von Zirkelbezügen.
Wie bei Newtonsoft.JsonReferenceResolver definiert die Klasse System.Text.Json.Serialization.ReferenceResolver das Verhalten bei Beibehaltung von Verweisen für Serialisierung und Deserialisierung. Erstellen Sie eine abgeleitete Klasse, um benutzerdefiniertes Verhalten anzugeben. Ein Beispiel finden Sie unter GuidReferenceResolver.
Einige verwandte Newtonsoft.Json
-Features werden nicht unterstützt:
Weitere Informationen finden Sie unter Beibehalten von Verweisen und Behandeln von Zirkelbezügen.
Wörterbuch mit Schlüssel, der keine Zeichenfolgen ist
Newtonsoft.Json
und System.Text.Json
unterstützen Sammlungen des Typs Dictionary<TKey, TValue>
. Informationen zu unterstützten Schlüsseltypen finden Sie unter Unterstützten Schlüsseltypen.
Achtung
Das Deserialisieren zu Dictionary<TKey, TValue>
, wo TKey
als etwas Anderes als string
beschrieben wird, könnte zu einem Sicherheitsrisiko in der nutzenden Anwendung führen. Weitere Informationen finden Sie unter dotnet/runtime#4761.
Typen ohne integrierte Unterstützung
System.Text.Json bietet für die folgenden Typen keine integrierte Unterstützung:
- DataTable und verwandte Typen (weitere Informationen finden Sie unter Unterstützte Typen)
- ExpandoObject
- TimeZoneInfo
- BigInteger
- DBNull
- Type
- ValueTuple und seine zugehörigen generischen Typen
Benutzerdefinierte Konverter können für Typen implementiert werden, für die keine integrierte Unterstützung vorhanden ist.
Polymorphe Serialisierung
Newtonsoft.Json
führt automatisch eine polymorphe Serialisierung durch. Ab .NET 7 unterstützt System.Text.Json die polymorphe Serialisierung mit dem JsonDerivedTypeAttribute-Attribut. Weitere Informationen finden Sie unter Serialisieren von Eigenschaften abgeleiteter Klassen.
Polymorphe Deserialisierung
Newtonsoft.Json
verfügt über eine TypeNameHandling
-Einstellung, mit der dem JSON-Code beim Serialisieren Typnamenmetadaten hinzugefügt werden. Sie verwendet die Metadaten während der Deserialisierung, um die polymorphe Deserialisierung durchzuführen. Ab .NET 7 basiert System.Text.Json auf Typdiskriminatorinformationen, um eine polymorphe Deserialisierung durchzuführen. Diese Metadaten werden im JSON-Code ausgegeben und dann während dem Deserialisieren verwendet, um zu bestimmen, ob als Basistyp oder als abgeleiteter Typ deserialisiert werden soll. Weitere Informationen finden Sie unter Serialisieren von Eigenschaften abgeleiteter Klassen.
Um die polymorphe Deserialisierung mit älteren .NET-Versionen zu unterstützen, erstellen Sie einen Konverter wie im Beispiel Schreiben von benutzerdefinierten Konvertern.
Deserialisieren von Enumerationswerten für Zeichenfolgen
Standardmäßig unterstützt System.Text.Json das Deserialisieren von Zeichenfolgenumwerten nicht, während dies für Newtonsoft.Json
der Fall ist. Der folgende Code löst z. B. eine JsonException aus:
string json = "{ \"Text\": \"Hello\", \"Enum\": \"Two\" }";
var _ = JsonSerializer.Deserialize<MyObj>(json); // Throws exception.
class MyObj
{
public string Text { get; set; } = "";
public MyEnum Enum { get; set; }
}
enum MyEnum
{
One,
Two,
Three
}
Sie können jedoch die Deserialisierung von Zeichenfolgenumwerten mithilfe des JsonStringEnumConverter-Konverters aktivieren. Weitere Informationen finden Sie unter Enumerationen als Zeichenfolgen.
Deserialisierung von Objekteigenschaften
Wenn Newtonsoft.Json
in Object deserialisieren, wird Folgendes ausgeführt:
- Es leitet den Typ primitiver Werte in der JSON-Nutzlast (außer
null
) ab und gibt die gespeicherten Typenstring
,long
,double
,boolean
oderDateTime
als geschachteltes Objekt zurück. Primitive Werte sind einzelne JSON-Werte, wie eine JSON-Zahl, -Zeichenfolge,true
,false
odernull
. - Gibt ein
JObject
oderJArray
für komplexe Werte in der JSON-Nutzlast zurück. Komplexe Werte sind Sammlungen von JSON-Schlüssel-Wert-Paaren in geschweiften Klammern ({}
) oder Listen mit Werten in eckigen Klammern ([]
). Die Eigenschaften und Werte in geschweiften oder eckigen Klammern können zusätzliche Eigenschaften oder Werte besitzen. - Gibt einen Nullverweis zurück, wenn die Nutzlast das JSON-Literal
null
enthält.
System.Text.Json speichert bei der Deserialisierung in JsonElement
ein geschachteltes Object sowohl für primitive als auch für komplexe Werte, z. B.:
- Eine
object
-Eigenschaft. - Ein
object
-Wörterbuchwert. - Ein
object
-Arraywert. - Ein Stamm-
object
.
System.Text.Json
behandelt null
jedoch genau wie Newtonsoft.Json
und gibt einen Nullverweis zurück, wenn die Nutzlast das JSON-Literal null
enthält.
Um Typrückschlüsse für object
-Eigenschaften zu implementieren, erstellen Sie einen Konverter wie in Schreiben von benutzerdefinierten Konvertern.
Deserialisieren eines Null-Typs in einen Non-Nullable-Typ
Newtonsoft.Json
löst im folgenden Szenario keine Ausnahme aus:
NullValueHandling
ist aufIgnore
festgelegt, und- Während der Deserialisierung enthält JSON einen Nullwert für einen Non-Nullable-Werttyp.
Im selben Szenario löst System.Text.Json eine Ausnahme aus. (Die entsprechende Einstellung in System.Text.Json
für die Behandlung von NULL ist JsonSerializerOptions.IgnoreNullValues = true
.)
Wenn Sie den Zieltyp besitzen, besteht die beste Problemumgehung darin, die betreffende Eigenschaft „nullable“ zu machen (z. B. int
in int?
ändern).
Eine weitere Problemumgehung besteht darin, einen Konverter für den Typ zu erstellen, wie im folgenden Beispiel, das Nullwerte für DateTimeOffset
-Typen behandelt:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SystemTextJsonSamples
{
public class DateTimeOffsetNullHandlingConverter : JsonConverter<DateTimeOffset>
{
public override DateTimeOffset Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
reader.TokenType == JsonTokenType.Null
? default
: reader.GetDateTimeOffset();
public override void Write(
Utf8JsonWriter writer,
DateTimeOffset dateTimeValue,
JsonSerializerOptions options) =>
writer.WriteStringValue(dateTimeValue);
}
}
Registrieren Sie diesen benutzerdefinierten Konverter mithilfe eines Attributs für die Eigenschaft oder durch Hinzufügen des Konverters zur Converters-Sammlung.
Hinweis: Der vorherige Konverter behandelt Nullwerte anders, als dies Newtonsoft.Json
für POCOS tut, die Standardwerte angeben. Angenommen, der folgende Code stellt Ihr Zielobjekt dar:
public class WeatherForecastWithDefault
{
public WeatherForecastWithDefault()
{
Date = DateTimeOffset.Parse("2001-01-01");
Summary = "No summary";
}
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string Summary { get; set; }
}
Und nehmen wir weiterhin an, der folgende JSON-Code wird mithilfe des vorherigen Konverters deserialisiert:
{
"Date": null,
"TemperatureCelsius": 25,
"Summary": null
}
Nach der Deserialisierung hat die Date
-Eigenschaft den Wert „1/1/0001“ (default(DateTimeOffset)
), d. h., der im Konstruktor festgelegte Wert wird überschrieben. Beim selben POCO und JSON-Code würde die Deserialisierung mit Newtonsoft.Json
den Wert „1/1/2001“ in der Date
-Eigenschaft belassen.
Deserialisieren in unveränderliche Klassen und Strukturen
Newtonsoft.Json
kann in unveränderliche Klassen und Strukturen deserialisieren, weil es Konstruktoren verwenden kann, die Parameter besitzen.
Geben Sie in System.Text.Json das Attribut [JsonConstructor] an, um die Verwendung eines parametrisierten Konstruktors festzulegen. Datensätze in C# 9 sind ebenfalls unveränderlich und werden als Deserialisierungsziele unterstützt. Weitere Informationen finden Sie unter Unveränderliche Typen und Datensätze.
Erforderliche Eigenschaften
In Newtonsoft.Json
geben Sie an, dass eine Eigenschaft erforderlich ist, indem Sie Required
für das [JsonProperty]
-Attribut festlegen. Newtonsoft.Json
löst eine Ausnahme aus, wenn im JSON für eine als erforderlich markierte Eigenschaft kein Wert empfangen wird.
Ab .NET 7 können Sie den C#-required
-Modifizierer oder das JsonRequiredAttribute-Attribut für eine erforderliche Eigenschaft verwenden. System.Text.Json löst eine Ausnahme aus, wenn die JSON-Nutzdaten keinen Wert für die markierte Eigenschaft enthalten. Weitere Informationen finden Sie unter Erforderliche Eigenschaften.
Angeben des Datumsformats
Newtonsoft.Json
bietet verschiedene Möglichkeiten, um zu kontrollieren, wie Eigenschaften des Typs DateTime
und DateTimeOffset
serialisiert und deserialisiert werden:
- Die
DateTimeZoneHandling
-Einstellung kann verwendet werden, um alleDateTime
-Werte als UTC-Datumsangaben zu serialisieren. - Die
DateFormatString
-Einstellung undDateTime
-Konverter können verwendet werden, um das Format von Datumszeichenfolgen anzupassen.
System.Text.Json unterstützt ISO 8601-1:2019 einschließlich des Profils RFC 3339. Dieses Format ist gängig, eindeutig und ermöglicht präzise Roundtrips. Um ein beliebiges anderes Format zu verwenden, erstellen Sie einen benutzerdefinierten Konverter. Die folgenden Konverter serialisieren und deserialisieren beispielsweise JSON-Code, der das Unix-Epochenformat mit oder ohne Zeitzonenversatz verwendet (Werte wie /Date(1590863400000-0700)/
oder /Date(1590863400000)/
):
sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
static readonly DateTimeOffset s_epoch = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)([+-])(\\d{2})(\\d{2})\\)/$", RegexOptions.CultureInvariant);
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
|| !int.TryParse(match.Groups[3].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
|| !int.TryParse(match.Groups[4].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
{
throw new JsonException();
}
int sign = match.Groups[2].Value[0] == '+' ? 1 : -1;
TimeSpan utcOffset = new(hours * sign, minutes * sign, 0);
return s_epoch.AddMilliseconds(unixTime).ToOffset(utcOffset);
}
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
TimeSpan utcOffset = value.Offset;
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");
writer.WriteStringValue(formatted);
}
}
sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
{
static readonly DateTime s_epoch = new(1970, 1, 1, 0, 0, 0);
static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)\\)/$", RegexOptions.CultureInvariant);
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string formatted = reader.GetString()!;
Match match = s_regex.Match(formatted);
if (
!match.Success
|| !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime))
{
throw new JsonException();
}
return s_epoch.AddMilliseconds(unixTime);
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime})/");
writer.WriteStringValue(formatted);
}
}
Weitere Informationen finden Sie unter Unterstützung von „DateTime“ und „DateTimeOffset“ in System.Text.Json.
Rückrufe
Newtonsoft.Json
ermöglicht das Ausführen von benutzerdefiniertem Code an mehreren Stellen im Serialisierungs- oder Deserialisierungsprozess:
- OnDeserializing (bei Beginn der Deserialisierung eines Objekts)
- OnDeserialized (nach Abschluss der Deserialisierung eines Objekts)
- OnSerializing (bei Beginn der Serialisierung eines Objekts)
- OnSerialized (nach Abschluss der Serialisierung eines Objekts)
System.Text.Json macht dieselben Benachrichtigungen während der Serialisierung und Deserialisierung verfügbar. Um sie zu verwenden, implementieren Sie eine oder mehrere der folgenden Schnittstellen aus dem Namespace System.Text.Json.Serialization:
Hier sehen Sie ein Beispiel, das nach einer NULL-Eigenschaft sucht und Meldungen zu Beginn und Ende der Serialisierung und Deserialisierung schreibt:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Callbacks
{
public class WeatherForecast :
IJsonOnDeserializing, IJsonOnDeserialized,
IJsonOnSerializing, IJsonOnSerialized
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
void IJsonOnDeserializing.OnDeserializing() => Console.WriteLine("\nBegin deserializing");
void IJsonOnDeserialized.OnDeserialized()
{
Validate();
Console.WriteLine("Finished deserializing");
}
void IJsonOnSerializing.OnSerializing()
{
Console.WriteLine("Begin serializing");
Validate();
}
void IJsonOnSerialized.OnSerialized() => Console.WriteLine("Finished serializing");
private void Validate()
{
if (Summary is null)
{
Console.WriteLine("The 'Summary' property is 'null'.");
}
}
}
public class Program
{
public static void Main()
{
var weatherForecast = new WeatherForecast
{
Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
};
string jsonString = JsonSerializer.Serialize(weatherForecast);
Console.WriteLine(jsonString);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString);
Console.WriteLine($"Date={weatherForecast?.Date}");
Console.WriteLine($"TemperatureCelsius={weatherForecast?.TemperatureCelsius}");
Console.WriteLine($"Summary={weatherForecast?.Summary}");
}
}
}
// output:
//Begin serializing
//The 'Summary' property is 'null'.
//Finished serializing
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":null}
//Begin deserializing
//The 'Summary' property is 'null'.
//Finished deserializing
//Date=8/1/2019 12:00:00 AM
//TemperatureCelsius = 25
//Summary=
Der OnDeserializing
-Code hat keinen Zugriff auf die neue POCO-Instanz. Um die neue POCO-Instanz zu Beginn der Deserialisierung zu bearbeiten, fügen Sie diesen Code in den POCO-Konstruktor ein.
Nicht öffentliche Setter und Getter von Eigenschaften
Newtonsoft.Json
kann private und interne Eigenschaften-Setter und -Getter über das JsonProperty
-Attribut verwenden.
System.Text.Json unterstützt private und interne Setter und Getter von Eigenschaften über das Attribut [JsonInclude]. Beispielcode finden Sie unter Nicht öffentliche Eigenschaftenaccessoren.
Auffüllen vorhandener Objekte
Die JsonConvert.PopulateObject
-Methode in Newtonsoft.Json
deserialisiert ein JSON-Dokument in eine vorhandene Instanz einer Klasse, anstatt eine neue Instanz zu erstellen. System.Text.Json erstellt immer eine neue Instanz des Zieltyps unter Verwendung des standardmäßigen öffentlichen parameterlosen Konstruktors. Benutzerdefinierte Konverter können in eine vorhandene Instanz deserialisieren.
Wiederverwenden statt Ersetzen von Eigenschaften
Ab .NET 8 System.Text.Json unterstützt die erneute Wiederverwendung initialisierter Eigenschaften, anstatt sie zu ersetzen. Es gibt einige Unterschiede im Verhalten, die Sie im API-Vorschlag nachlesen können.
Weitere Informationen finden Sie unter Auffüllen initialisierter Eigenschaften.
Auffüllen von Eigenschaften ohne Setter
Ab .NET 8 System.Text.Json wird das Auffüllen von Eigenschaften unterstützt, auch von solchen, die keinen Setter haben. Weitere Informationen finden Sie unter Auffüllen initialisierter Eigenschaften.
Snake-Case-Benennungsrichtlinie
System.Text.Json enthält eine integrierte Benennungsrichtlinie für Snake Case. Bei einigen Eingaben gibt es jedoch einige Verhaltensunterschiede Newtonsoft.Json
. Die folgende Tabelle zeigt einige dieser Unterschiede beim Konvertieren von Eingaben mithilfe der JsonNamingPolicy.SnakeCaseLower-Richtlinie.
Eingabe | Newtonsoft.Json-Ergebnis | System.Text.Json-Ergebnis |
---|---|---|
„AB1“ | „a_b1“ | „ab1“ |
„SHA512Managed“ | „sh_a512_managed“ | „sha512_managed“ |
„abc123DEF456“ | „abc123_de_f456“ | „abc123_def456“ |
„KEBAB-CASE“ | „keba_b-_case“ | „kebab-case“ |
System.Runtime.Serialization-Attribute
Mit System.Runtime.Serialization- Attributen wie DataContractAttribute, DataMemberAttributeund IgnoreDataMemberAttribute können Sie einen Datenvertrag definieren. Ein neuer Datenvertrag ist eine formale Vereinbarung zwischen einem Dienst und einem Client, in dem die auszutauschenden Daten abstrakt beschrieben werden. Der Datenvertrag definiert genau, welche Eigenschaften für den Austausch serialisiert werden.
System.Text.Json verfügt über keine integrierte Unterstützung für diese Attribute. Ab .NET 7 können Sie jedoch einen benutzerdefinierten Typlöser verwenden, um Unterstützung hinzuzufügen. Ein Beispiel finden Sie unter ZCS. DataContractResolver.
Oktalzahlen
Newtonsoft.Json
behandelt Zahlen mit einer führenden Null als Oktalzahlen. System.Text.Json lässt keine führenden Nullen zu, da sie von der Spezifikation RFC 8259 nicht zugelassen werden.
Behandeln fehlender Member
Newtonsoft.Json
kann so konfiguriert werden, dass Ausnahmen ausgelöst werden, wenn der deserialisierte JSON-Code Eigenschaften enthält, die im Zieltyp fehlen. Standardmäßig ignoriert System.Text.Json zusätzliche Eigenschaften im JSON-Code, außer wenn Sie das Attribut [JsonExtensionData] verwenden.
In .NET 8 und späteren Versionen können Sie festlegen, ob nicht zugeordnete JSON-Eigenschaften übersprungen oder nicht zugelassen werden sollen, indem Sie eine der folgenden Möglichkeiten nutzen:
- Wenden Sie das Attribut JsonUnmappedMemberHandlingAttribute auf den Typ an, auf den Sie deserialisieren möchten.
- Wenn Sie Ihre Einstellung global festlegen möchten, legen Sie die Eigenschaft JsonSerializerOptions.UnmappedMemberHandling fest. Oder legen Sie für die Quellgenerierung die Eigenschaft JsonSourceGenerationOptionsAttribute.UnmappedMemberHandling fest, und wenden Sie das Attribut auf Ihre Klasse JsonSerializerContext an.
- Passen Sie die Eigenschaft JsonTypeInfo.UnmappedMemberHandling an.
JsonObjectAttribute
Newtonsoft.Json
verfügt über ein Attribut namens JsonObjectAttribute
, das auf Typebene angewendet werden kann, um zu steuern, welche Member serialisiert werden, wie null
Werte behandelt werden und ob alle Member erforderlich sind. System.Text.Json verfügt über kein entsprechendes Attribut, das auf einen Typ angewendet werden kann. Für einige Verhaltensweisen, z. B. die Behandlung von null
-Werten, können Sie entweder dasselbe Verhalten für die globale Ebene JsonSerializerOptions oder einzeln für jede Eigenschaft konfigurieren.
Betrachten Sie das folgende Beispiel, in dem Newtonsoft.Json.JsonObjectAttribute
verwendet wird, um anzugeben, dass alle null
-Eigenschaften ignoriert werden sollen:
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class Person { ... }
In System.Text.Json können Sie das Verhalten für alle Typen und Eigenschaften festlegen:
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
string json = JsonSerializer.Serialize<Person>(person, options);
Alternativ können Sie das Verhalten für jede Eigenschaft separat festlegen:
public class Person
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Name { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Age { get; set; }
}
Betrachten Sie als Nächstes das folgende Beispiel, in dem Newtonsoft.Json.JsonObjectAttribute
verwendet wird, um anzugeben, dass alle Membereigenschaften im JSON-Code vorhanden sein müssen:
[JsonObject(ItemRequired = Required.Always)]
public class Person { ... }
Sie können das gleiche Verhalten in System.Text.Json erzielen, indem Sie den C#-Modifizierer required
oder JsonRequiredAttributezu jeder Eigenschaft hinzufügen. Weitere Informationen finden Sie unter Erforderliche Eigenschaften.
public class Person
{
[JsonRequired]
public string? Name { get; set; }
public required int? Age { get; set; }
}
TraceWriter
Mit Newtonsoft.Json
können Sie Debuggen, indem Sie einen TraceWriter
verwenden, um Protokolle anzuzeigen, die von der Serialisierung oder Deserialisierung generiert werden. System.Text.Json führt keine Protokollierung aus.
„JsonDocument“ und „JsonElement“ im Vergleich zu „JToken“ (wie „JObject“, „JArray“)
System.Text.Json.JsonDocument bietet die Möglichkeit, ein schreibgeschütztes Dokumentobjektmodell (DOM) aus vorhandenen JSON-Nutzlasten zu analysieren und zu erstellen. Das DOM bietet zufälligen Zugriff auf Daten in einer JSON-Nutzlast. Auf die JSON-Elemente, aus denen sich die Nutzlast zusammensetzt, kann über den Typ JsonElement zugegriffen werden. Der JsonElement
-Typ stellt APIs zum Konvertieren von JSON-Text in allgemeine .NET-Typen bereit. JsonDocument
macht eine RootElement-Eigenschaft verfügbar.
Ab .NET 6 können Sie mithilfe des -Typs und anderer Typen im JsonNode-Namespace ein System.Text.Json.Nodes DOM aus vorhandenen JSON-Nutzdaten parsen und erstellen. Weitere Informationen finden Sie unter Verwenden von JsonNode
.
„JsonDocument“ ist „IDisposable“
JsonDocument
erstellt eine In-Memory-Ansicht der Daten in einem gepoolten Puffer. Daher implementiert der JObject
-Typ JArray
, im Gegensatz zu Newtonsoft.Json
oder JsonDocument
von IDisposable
, und muss innerhalb eines using-Blocks verwendet werden. Weitere Informationen finden Sie unter „JsonDocument“ ist „IDisposable“.
Das „JsonDocument“ ist schreibgeschützt.
Das System.Text.Json-DOM kann keine JSON-Elemente hinzufügen, entfernen oder ändern. Es ist auf diese Weise konzipiert, um Leistung zu bieten und Zuordnungen für das Parsen gängiger JSON-Nutzdatengrößen (d. h. < 1 MB) zu verringern.
„JsonElement“ ist eine union-Struktur
JsonDocument
macht das RootElement
als Eigenschaft des Typs JsonElement verfügbar, wobei es sich um einen Union-Strukturtyp handelt, der jedes JSON-Element umfasst. Newtonsoft.Json
verwendet dedizierte hierarchische Typen wie JObject
, JArray
, JToken
usw. JsonElement
ist das, was Sie durchsuchen und worüber Sie aufzählen können, und Sie können JsonElement
verwenden, um JSON-Elemente in .NET-Typen zu materialisieren.
Ab .NET 6 können Sie Typ JsonNode und Typen im System.Text.Json.Nodes-Namespace verwenden, die JObject
, JArray
und JToken
entsprechen. Weitere Informationen finden Sie unter Verwenden von JsonNode
.
Durchsuchen eines „JSonDocument“ und „JsonElement“ nach Unterelementen
Suchen nach JSON-Token mithilfe von JObject
oder JArray
von Newtonsoft.Json
sind in der Regel relativ schnell, da es sich dabei um Nachschlagevorgänge in einem Wörterbuch handelt. Im Vergleich dazu erfordern Suchen im JsonElement
eine sequenzielle Suche der Eigenschaften, sodass sie relativ langsam sind (z. B. beim Verwenden von TryGetProperty
). System.Text.Json ist darauf ausgelegt, die anfängliche Analysezeit zu minimieren anstatt die Nachschlagezeit. Weitere Informationen finden Sie unter Durchsuchen von „JSonDocument“ und „JsonElement“ nach Unterelementen.
Utf8JsonReader und JsonTextReader
Bei System.Text.Json.Utf8JsonReader handelt es sich um einen leistungsstarken Vorwärtsreader mit geringer Zuordnung für UTF-8-kodierten JSON-Text, der aus einer ReadOnlySpan<byte> oder ReadOnlySequence<byte> gelesen wird. Der Utf8JsonReader
ist ein Low-Level-Typ, der zum Erstellen von benutzerdefinierten Parsern und Deserialisierungsprogrammen genutzt werden kann.
„Utf8JsonReader“ ist eine ref-Struktur.
Beim JsonTextReader
in Newtonsoft.Json
handelt es sich um eine Klasse. Der Utf8JsonReader
-Typ unterscheidet sich darin, dass es sich um eine Referenzstruktur handelt. Weitere Informationen finden Sie unter Einschränkungen bei „ref struct“ für Utf8JsonReader.
Lesen von Nullwerten in Nullable-Werttypen
Newtonsoft.Json
bietet APIs, die Nullable<T> zurückgeben, z. B. ReadAsBoolean
, das einen Null
TokenType
für Sie verarbeitet, indem es einen bool?
zurückgibt. Die integrierten System.Text.Json
-APIs geben nur Non-Nullable-Werttypen zurück. Weitere Informationen finden Sie unter Lesen von NULL-Werten in Nullwerte zulassende Werttypen.
Mehrere Ziele zum Lesen von JSON-Code
Wenn Sie weiterhin Newtonsoft.Json
für bestimmte Zielframeworks verwenden müssen, können Sie mehrere Zielversionen verwenden und zwei Implementierungen verwenden. Dies ist jedoch nicht trivial und erfordert einige #ifdefs
sowie Quellduplizierung. Eine Möglichkeit, so viel Code wie möglich gemeinsam zu verwenden, besteht darin, ref struct
und Utf8JsonReader in einen Newtonsoft.Json.JsonTextReader
-Wrapper einzuschließen. Mit diesem Wrapper wird der öffentliche Oberflächenbereich vereinheitlicht, während die Verhaltensunterschiede isoliert werden. Auf diese Weise können Sie die Änderungen hauptsächlich auf die Konstruktion des Typs beschränken und den neuen Typ gleichzeitig als Verweis übergeben. Dies ist das Muster, an dem sich die Microsoft.Extensions.DependencyModel-Bibliothek orientiert:
Utf8JsonWriter und JsonTextWriter
Mit System.Text.Json.Utf8JsonWriter lassen sich in UTF-8 codierte JSON-Texte aus gängigen .NET-Typen wie String
, Int32
und DateTime
schnell mit hohem Durchsatz schreiben. Der Writer ist ein Low-Level-Typ, der zum Erstellen von benutzerdefinierten Serialisierungsmodulen genutzt werden kann.
Schreiben von Rohwerten
Newtonsoft.Json
enthält eine WriteRawValue
-Methode, die JSON-Rohcode schreibt, wenn ein Wert erwartet wird. System.Text.Json hat eine direkte Entsprechung: Utf8JsonWriter.WriteRawValue. Weitere Informationen finden Sie unter Schreiben von JSON-Rohdaten.
Anpassen des JSON-Formats
JsonTextWriter
umfasst die folgenden Einstellungen, für die es bei Utf8JsonWriter keine Entsprechung gibt:
- QuoteChar: Gibt das Zeichen an, das zum Umschließen von Zeichenfolgenwerten verwendet werden soll.
Utf8JsonWriter
verwendet immer doppelte Anführungszeichen. - QuoteName: Gibt an, ob Eigenschaftsnamen in Anführungszeichen gesetzt werden sollen oder nicht.
Utf8JsonWriter
umschließt sie immer mit Anführungszeichen.
Ab .NET 9 können Sie das Einzugszeichen und die Größe für Utf8JsonWriter mithilfe von Optionen anpassen, die von der JsonWriterOptions-Struktur verfügbar gemacht werden:
JsonTextWriter
umfasst die folgenden Einstellungen, für die es bei Utf8JsonWriter
keine Entsprechung gibt:
- Indentation: Gibt an, um wie viele Zeichen ein Einzug erfolgen soll.
Utf8JsonWriter
zieht immer um 2 Zeichen ein. - IndentChar: Gibt das für Einzüge zu verwendende Zeichen an.
Utf8JsonWriter
verwendet immer Leerzeichen. - QuoteChar: Gibt das Zeichen an, das zum Umschließen von Zeichenfolgenwerten verwendet werden soll.
Utf8JsonWriter
verwendet immer doppelte Anführungszeichen. - QuoteName: Gibt an, ob Eigenschaftsnamen in Anführungszeichen gesetzt werden sollen oder nicht.
Utf8JsonWriter
umschließt sie immer mit Anführungszeichen.
Es gibt keine Problemumgehungen, mit denen Sie den von Utf8JsonWriter
auf diese Weisen erzeugten JSON-Code anpassen können.
Schreiben von TimeSpan-, Uri- oder char-Werten
JsonTextWriter
stellt WriteValue
-Methoden für TimeSpan-, URI- und char-Werte bereit. Utf8JsonWriter
verfügt über keine entsprechenden Methoden. Formatieren Sie diese Werte stattdessen als Zeichenfolgen (z. B. durch Aufrufen von ToString()
), und rufen Sie WriteStringValue auf.
Mehrere Ziele zum Schreiben von JSON-Code
Wenn Sie weiterhin Newtonsoft.Json
für bestimmte Zielframeworks verwenden müssen, können Sie mehrere Zielversionen verwenden und zwei Implementierungen verwenden. Dies ist jedoch nicht trivial und erfordert einige #ifdefs
sowie Quellduplizierung. Eine Möglichkeit, so viel Code wie möglich gemeinsam zu verwenden, besteht darin, Utf8JsonWriter und Newtonsoft.Json.JsonTextWriter
in einen Wrapper einzuschließen. Mit diesem Wrapper wird der öffentliche Oberflächenbereich vereinheitlicht, während die Verhaltensunterschiede isoliert werden. Auf diese Weise können Sie die Änderungen hauptsächlich auf die Konstruktion des Typs beschränken. Die Microsoft.Extensions.DependencyModel-Bibliothek orientiert sich an:
„TypeNameHandling.All“ nicht unterstützt
Die Entscheidung, die TypeNameHandling.All
-äquivalente Funktionalität aus System.Text.Json
auszuschließen, wurde absichtlich getroffen. Das Angeben der eigenen Typinformationen durch eine JSON-Nutzdaten ist eine häufige Ursache von Sicherheitsrisiken in Webanwendungen. Insbesondere ermöglicht das Konfigurieren von Newtonsoft.Json
mit TypeNameHandling.All
dem Remoteclient das Einbetten einer gesamten ausführbaren Anwendung in den JSON-Nutzdaten, sodass die Webanwendung während der Deserialisierung den eingebetteten Code extrahiert und ausführt. Weitere Informationen finden Sie auf der PowerPoint-Präsentation zu „Friday the 13th: JSON Attacks“ und in den Details zu „Friday the 13th: JSON Attacks“.
JSON-Pfadabfragen werden nicht unterstützt
Das JsonDocument
-DOM unterstützt keine Abfragen mithilfe des JSON-Pfads.
In einem JsonNode-DOM verfügt jede JsonNode
-Instanz über eine GetPath
-Methode, die einen Pfad zu diesem Knoten zurückgibt. Allerdings ist keine integrierte API zum Verarbeiten von Abfragen basierend auf JSON-Pfadabfragezeichenfolgen vorhanden.
Weitere Informationen finden Sie unter dem GitHub-Issue „dotnet/runtime #31068“.
Einige Grenzwerte sind nicht konfigurierbar
System.Text.Json legt Grenzwerte fest, die für einige Werte nicht geändert werden können, z. B. die maximale Tokengröße in Zeichen (166 MB) und in Base 64 (125 MB). Weitere Informationen finden Sie JsonConstants
im Quellcode und im GitHub-Issue dotnet/runtime #39953.
„NaN“, „Infinity“, „-Infinity“
Newtonsoft parst die JSON-Zeichenfolgentoken NaN
, Infinity
und -Infinity
. Bei System.Text.Json verwenden Sie JsonNumberHandling.AllowNamedFloatingPointLiterals. Informationen zum Verwenden dieser Einstellung finden Sie unter Zulassen oder Schreiben von Zahlen in Anführungszeichen.
Verwenden von GitHub Copilot zum Migrieren
Sie können von GitHub Copilot Unterstützung bei der Codierung erhalten, um Ihren Code in Ihrer IDE zu konvertieren.
Wenn Sie Visual Studio 2022, Version 17.8 oder höher verwenden, können Sie GitHub Copilot in Visual Studio mit KI-Unterstützung ausprobieren, das Ihnen die Migration Ihres Newtonsoft.Json
-Codes vereinfachen wird, damit Sie System.Text.Json
verwenden können. Reichen Sie im Chat-Fenster von Copilot Ihre Frage und den Code ein, der als Eingabeaufforderung konvertiert werden soll. Sehen Sie sich hierzu das folgende Beispiel an.
Hinweis
GitHub Copilot wird von KI unterstützt. Daher sind Überraschungen und Fehler möglich. Überprüfen Sie jeden generierten Code oder alle Vorschläge. Weitere Informationen zur allgemeinen Verwendung von GitHub Copilot, zu den Auswirkungen des Produkts, zur menschlichen Aufsicht und zum Datenschutz finden Sie unter Häufig gestellte Fragen zu GitHub Copilot.
Beispiel für eine Eingabeaufforderung für Copilot Chat
convert the following code to use System.Text.Json
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2024, 08, 08);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonConvert.SerializeObject(product);
Console.WriteLine(output);
Beispiel für eine Copilot Chat-Antwort
To convert the code to use System.Text.Json, you can use the JsonSerializer class. Here's the updated code:
using System;
using System.Text.Json;
public class Product
{
public string Name { get; set; }
public DateTime ExpiryDate { get; set; }
public decimal Price { get; set; }
public string[] Sizes { get; set; }
}
public class Program
{
public static void Main()
{
Product product = new Product();
product.Name = "Apple";
product.ExpiryDate = new DateTime(2024, 08, 08);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string output = JsonSerializer.Serialize(product);
Console.WriteLine(output);
}
}
This code uses System.Text.Json.JsonSerializer.Serialize to convert the Product object to a JSON string.
Beachten Sie, dass die Ergebnisse möglicherweise von den in diesen Beispielantworten gezeigten Ergebnissen abweichen können. KI-Modelle sind nicht deterministisch. Das bedeutet, dass sie auf die gleiche Frage verschiedene Antworten zurückgeben können. Dies kann auf zusätzliche Lernaktivitäten und Anpassung im Laufe der Zeit, Sprachvariation, Änderungen im Kontext, wie z. B. Ihren Chatverlauf und viele weiter Faktoren zurückzuführen sein.
Sie können Chat-Funktionen wie Slash-Befehle, Verweise und Threads verwenden, um eine Absicht festzulegen und bessere Antworten mit bereichsbezogenem Kontext zu erhalten.
Wenn Ihre Codedatei filename
beispielsweise in der IDE geöffnet ist, können Sie auf die Datei verweisen, indem Sie in Ihrer Eingabeaufforderung an Copilot Chat „#filename
konvertieren, um System.Text.Json
zu verwenden“ eingeben. Oder Sie können auf die Lösung verweisen, indem Sie im Chatfenster oder im Inline-Chat „ konvertieren@workspace
, um System.Text.Json
zu verwenden“ eingeben.