Migration von Newtonsoft.Json zu System.Text.JsonHow to migrate from Newtonsoft.Json to System.Text.Json

In diesem Artikel wird erläutert, wie Sie von Newtonsoft.Json zu System.Text.Json migrieren.This article shows how to migrate from Newtonsoft.Json to System.Text.Json.

Der System.Text.Json-Namespace bietet Funktionalitäten zum Serialisieren in und Deserialisieren aus JSON (JavaScript Object Notation).The System.Text.Json namespace provides functionality for serializing to and deserializing from JavaScript Object Notation (JSON). Die System.Text.Json-Bibliothek ist im ist im freigegebenen .NET Core 3.0-Framework enthalten.The System.Text.Json library is included in the .NET Core 3.0 shared framework. Installieren Sie für andere Zielframeworks das NuGet-Paket System.Text.Json.For other target frameworks, install the System.Text.Json NuGet package. Das Paket unterstützt:The package supports:

  • .NET Standard 2.0 und höhere Versionen.NET Standard 2.0 and later versions
  • .NET Framework 4.7.2 und höhere Versionen.NET Framework 4.7.2 and later versions
  • .NET Core 2.0, 2.1 und 2.2.NET Core 2.0, 2.1, and 2.2

System.Text.Json konzentriert sich hauptsächlich auf Leistung, Sicherheit und Einhaltung von Standards.System.Text.Json focuses primarily on performance, security, and standards compliance. Es weist einige wesentliche Unterschiede beim Standardverhalten auf und zielt nicht auf Featureparität mit Newtonsoft.Json ab.It has some key differences in default behavior and doesn't aim to have feature parity with Newtonsoft.Json. In einigen Szenarien verfügt System.Text.Json über keine integrierte Funktionalität, doch gibt es dafür empfohlene Problemumgehungen.For some scenarios, System.Text.Json has no built-in functionality, but there are recommended workarounds. In anderen Szenarien sind Problemumgehungen nicht praktikabel.For other scenarios, workarounds are impractical. Wenn Ihre Anwendung von einer fehlenden Funktion abhängig ist, sollten Sie erwägen, ein Issue zu registrieren, um herauszufinden, ob Unterstützung für Ihr Szenario hinzugefügt werden kann.If your application depends on a missing feature, consider filing an issue to find out if support for your scenario can be added.

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.Most of this article is about how to use the JsonSerializer API, but it also includes guidance on how to use the JsonDocument (which represents the Document Object Model or DOM), Utf8JsonReader, and Utf8JsonWriter types.

Tabelle mit Unterschieden zwischen Newtonsoft.Json und System.Text.JsonTable of differences between Newtonsoft.Json and System.Text.Json

In der folgenden Tabelle sind die Newtonsoft.Json-Funktionen mit ihren Entsprechungen in System.Text.Json aufgeführt.The following table lists Newtonsoft.Json features and System.Text.Json equivalents. Die Entsprechungen lassen sich in die folgenden Kategorien einteilen:The equivalents fall into the following categories:

  • Unterstützt durch integrierte Funktionalität.Supported by built-in functionality. Um ein ähnliches Verhalten von System.Text.Json zu erzielen, ist möglicherweise die Verwendung eines Attributs oder einer globalen Option erforderlich.Getting similar behavior from System.Text.Json may require the use of an attribute or global option.
  • Nicht unterstützt, Problemumgehung ist möglich.Not supported, workaround is possible. Die Problemumgehungen sind benutzerdefinierte Konverter, die möglicherweise keine vollständige Parität mit der Newtonsoft.Json-Funktionalität bereitstellen.The workarounds are custom converters, which may not provide complete parity with Newtonsoft.Json functionality. Für einige davon wird Beispielcode als Beispiele bereitgestellt.For some of these, sample code is provided as examples. Wenn Sie von diesen Newtonsoft.Json-Funktionen abhängig sind, erfordert die Migration Änderungen an Ihren .NET-Objektmodellen oder andere Codeänderungen.If you rely on these Newtonsoft.Json features, migration will require modifications to your .NET object models or other code changes.
  • Nicht unterstützt, Problemumgehung ist nicht praktikabel oder nicht möglich.Not supported, workaround is not practical or possible. Wenn Sie von diesen Newtonsoft.Json-Funktionen abhängig sind, ist die Migration nicht ohne wesentliche Änderungen möglich.If you rely on these Newtonsoft.Json features, migration will not be possible without significant changes.
Feature in Newtonsoft.JsonNewtonsoft.Json feature Äquivalent in System.Text.JsonSystem.Text.Json equivalent
Standardmäßige Deserialisierung ohne Berücksichtigung von Groß-/KleinschreibungCase-insensitive deserialization by default ✔️ Globale Einstellung „PropertyNameCaseInsensitive“✔️ PropertyNameCaseInsensitive global setting
Eigenschaftsnamen mit Camel-Case-SchreibweiseCamel-case property names ✔️ Globale Einstellung „PropertyNamingPolicy“✔️ PropertyNamingPolicy global setting
Minimales Escapen von ZeichenMinimal character escaping ✔️ Strenges Escapen von Zeichen, konfigurierbar✔️ Strict character escaping, configurable
Globale Einstellung NullValueHandling.IgnoreNullValueHandling.Ignore global setting ✔️ Globale Option „IgnoreNullValues“✔️ IgnoreNullValues global option
Kommentare zulassenAllow comments ✔️ Globale Einstellung „ReadCommentHandling“✔️ ReadCommentHandling global setting
Nachfolgende Kommas zulassenAllow trailing commas ✔️ Globale Einstellung „AllowTrailingCommas“✔️ AllowTrailingCommas global setting
Registrierung benutzerdefinierter KonverterCustom converter registration ✔️ Rangordnung weicht ab✔️ Order of precedence differs
Keine standardmäßige maximale TiefeNo maximum depth by default ✔️ Standardmäßige maximale Tiefe von  64, konfigurierbar✔️ Default maximum depth 64, configurable
Unterstützung für ein breites Spektrum von TypenSupport for a broad range of types ⚠️ Einige Typen erfordern benutzerdefinierte Konverter⚠️ Some types require custom converters
Deserialisieren von Zeichenfolgen als ZahlenDeserialize strings as numbers ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Deserialisieren von Dictionary mit Nicht-Zeichenfolgen-SchlüsselDeserialize Dictionary with non-string key ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Polymorphe SerialisierungPolymorphic serialization ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Polymorphe DeserialisierungPolymorphic deserialization ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Deserialisieren eines abgeleiteten Typs in object-EigenschaftenDeserialize inferred type to object properties ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Deserialisieren des JSON-Literals null in Non-Nullable-WerttypenDeserialize JSON null literal to non-nullable value types ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Deserialisieren in unveränderliche Klassen und StrukturenDeserialize to immutable classes and structs ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
[JsonConstructor]-Attribut[JsonConstructor] attribute ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Required-Einstellung für [JsonProperty]-AttributRequired setting on [JsonProperty] attribute ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
NullValueHandling-Einstellung für [JsonProperty]-AttributNullValueHandling setting on [JsonProperty] attribute ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
DefaultValueHandling-Einstellung für [JsonProperty]-AttributDefaultValueHandling setting on [JsonProperty] attribute ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Globale Einstellung DefaultValueHandlingDefaultValueHandling global setting ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
DefaultContractResolver zum Ausschließen von EigenschaftenDefaultContractResolver to exclude properties ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Einstellungen DateTimeZoneHandling und DateFormatStringDateTimeZoneHandling, DateFormatString settings ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
RückrufeCallbacks ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround, sample
Unterstützung für öffentliche und nicht öffentliche FelderSupport for public and non-public fields ⚠️ Nicht unterstützt, Problemumgehung, Beispiel⚠️ Not supported, workaround
Unterstützung für interne und private Eigenschaften-Setter und -GetterSupport for internal and private property setters and getters ⚠️ Nicht unterstützt, Problemumgehung⚠️ Not supported, workaround
JsonConvert.PopulateObject-MethodeJsonConvert.PopulateObject method ⚠️ Nicht unterstützt, Problemumgehung⚠️ Not supported, workaround
Globale Einstellung ObjectCreationHandlingObjectCreationHandling global setting ⚠️ Nicht unterstützt, Problemumgehung⚠️ Not supported, workaround
Zu Sammlungen hinzufügen ohne SetterAdd to collections without setters ⚠️ Nicht unterstützt, Problemumgehung⚠️ Not supported, workaround
Globale Einstellung PreserveReferencesHandlingPreserveReferencesHandling global setting Nicht unterstütztNot supported
Globale Einstellung ReferenceLoopHandlingReferenceLoopHandling global setting Nicht unterstütztNot supported
Unterstützung für System.Runtime.Serialization-AttributeSupport for System.Runtime.Serialization attributes Nicht unterstütztNot supported
Globale Einstellung MissingMemberHandlingMissingMemberHandling global setting Nicht unterstütztNot supported
Eigenschaftsnamen ohne Anführungszeichen zulassenAllow property names without quotes Nicht unterstütztNot supported
Einschließen von Zeichenfolgenwerten in einfache Anführungszeichen zulassenAllow single quotes around string values Nicht unterstütztNot supported
JSON-Werte, die keine Zeichenfolgen sind, für Zeichenfolgeneigenschaften zulassenAllow non-string JSON values for string properties Nicht unterstütztNot supported

Dies ist keine vollständige Liste der Newtonsoft.Json-Funktionen.This is not an exhaustive list of Newtonsoft.Json features. Die Liste enthält viele der Szenarien, die in GitHub-Issues oder StackOverflow-Beiträgen angefordert wurden.The list includes many of the scenarios that have been requested in GitHub issues or StackOverflow posts. 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.If you implement a workaround for one of the scenarios listed here that doesn't currently have sample code, and if you want to share your solution, select This page in the Feedback section at the bottom of this page. Dadurch wird ein Issue im GitHub-Repository dieser Dokumentation erstellt und dieses ebenfalls im Abschnitt Feedback auf dieser Seite aufgeführt.That creates an issue in this documentation's GitHub repo and lists it in the Feedback section on this page too.

Unterschiede beim Standardverhalten von JsonSerializer im Vergleich zu Newtonsoft.JsonDifferences in default JsonSerializer behavior compared to Newtonsoft.Json

System.Text.Json ist standardmäßig strikt und vermeidet jegliche Vermutung oder Interpretation im Namen des Aufrufers, womit deterministisches Verhalten betont wird.System.Text.Json is strict by default and avoids any guessing or interpretation on the caller's behalf, emphasizing deterministic behavior. Die Bibliothek ist absichtlich auf diese Weise für Leistung und Sicherheit konzipiert.The library is intentionally designed this way for performance and security. Newtonsoft.Json ist standardmäßig flexibel.Newtonsoft.Json is flexible by default. Dieser grundlegende Unterschied beim Design steht hinter vielen der folgenden spezifischen Unterschiede im Standardverhalten.This fundamental difference in design is behind many of the following specific differences in default behavior.

Deserialisierung ohne Berücksichtigung von Groß-/KleinschreibungCase-insensitive deserialization

Während der Deserialisierung führt Newtonsoft.Json standardmäßig einen Abgleich der Eigenschaftsnamen ohne Berücksichtigung von Groß-/Kleinschreibung durch.During deserialization, Newtonsoft.Json does case-insensitive property name matching by default. Das Standardverhalten von System.Text.Json berücksichtigt die Groß-/Kleinschreibung, was eine bessere Leistung liefert, weil ein exakter Abgleich erfolgt.The System.Text.Json default is case-sensitive, which gives better performance since it's doing an exact match. Informationen, wie Sie einen Abgleich ohne Berücksichtigung von Groß-/Kleinschreibung durchführen, finden Sie unter Eigenschaftenabgleich ohne Berücksichtigung von Groß-/Kleinschreibung.For information about how to do case-insensitive matching, see Case-insensitive property matching.

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.If you're using System.Text.Json indirectly by using ASP.NET Core, you don't need to do anything to get behavior like Newtonsoft.Json. 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 specifies the settings for camel-casing property names and case-insensitive matching when it uses System.Text.Json. Die Standardwerte werden in der JsonOptions-Klasse festgelegt.The default values are set in the JsonOptions class.

Minimales Escapen von ZeichenMinimal character escaping

Während der Serialisierung ist Newtonsoft.Json relativ nachsichtig, wenn es um das Durchlassen von Zeichen geht, ohne sie zu escapen.During serialization, Newtonsoft.Json is relatively permissive about letting characters through without escaping them. Dies bedeutet, dass sie nicht durch \uxxxx ersetzt werden, wobei xxxx der Codepunkt des Zeichens ist.That is, it doesn't replace them with \uxxxx where xxxx is the character's code point. Wenn sie escapet werden, geschieht dies durch Ausgabe eines umgekehrten Schrägstrichs (\) vor dem Zeichen (z. B. wird " zu \").Where it does escape them, it does so by emitting a \ before the character (for example, " becomes \"). 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 escapes more characters by default to provide defense-in-depth protections against cross-site scripting (XSS) or information-disclosure attacks and does so by using the six-character sequence. 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 escapes all non-ASCII characters by default, so you don't need to do anything if you're using StringEscapeHandling.EscapeNonAscii in Newtonsoft.Json. System.Text.Json escapet außerdem standardmäßig HTML-abhängige Zeichen.System.Text.Json also escapes HTML-sensitive characters, by default. Informationen, wie Sie das Standardverhalten von System.Text.Json außer Kraft setzen können, finden Sie unter Anpassen der Zeichencodierung.For information about how to override the default System.Text.Json behavior, see Customize character encoding.

KommentareComments

Während der Deserialisierung ignoriert Newtonsoft.Json standardmäßig Kommentare in der JSON-Datei.During deserialization, Newtonsoft.Json ignores comments in the JSON by default. Das Standardverhalten von System.Text.Json besteht im Auslösen von Ausnahmen für Kommentare, weil die Spezifikation RFC 8259 diese nicht umfasst.The System.Text.Json default is to throw exceptions for comments because the RFC 8259 specification doesn't include them. Informationen, wie Sie Kommentare zulassen können, finden Sie unter Zulassen von Kommentaren und nachfolgenden Kommas.For information about how to allow comments, see Allow comments and trailing commas.

Nachfolgende KommasTrailing commas

Während der Deserialisierung ignoriert Newtonsoft.Json standardmäßig nachfolgende Kommas.During deserialization, Newtonsoft.Json ignores trailing commas by default. Es ignoriert ferner mehrere nachfolgende Kommas (z. B. [{"Color":"Red"},{"Color":"Green"},,]).It also ignores multiple trailing commas (for example, [{"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.The System.Text.Json default is to throw exceptions for trailing commas because the RFC 8259 specification doesn't allow them. Informationen, wie Sie System.Text.Json dazu bringen, diese zu akzeptieren, finden Sie unter Zulassen von Kommentaren und nachfolgenden Kommas.For information about how to make System.Text.Json accept them, see Allow comments and trailing commas. Es gibt keine Möglichkeit, mehrere nachfolgende Kommas zuzulassen.There's no way to allow multiple trailing commas.

Rangfolge für die Registrierung von KonverternConverter registration precedence

Die Rangfolge der Registrierung von benutzerdefinierten Konvertern in Newtonsoft.Json ist wie folgt:The Newtonsoft.Json registration precedence for custom converters is as follows:

  • Attribut auf EigenschaftsebeneAttribute on property
  • Attribut auf TypebeneAttribute on type
  • Converters-SammlungConverters collection

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.This order means that a custom converter in the Converters collection is overridden by a converter that is registered by applying an attribute at the type level. Beide dieser Registrierungen werden von einem Attribut auf Eigenschaftsebene außer Kraft gesetzt.Both of those registrations are overridden by an attribute at the property level.

Die Rangfolge der Registrierung von benutzerdefinierten Konvertern in System.Text.Json weicht hiervon ab:The System.Text.Json registration precedence for custom converters is different:

  • Attribut auf EigenschaftsebeneAttribute on property
  • Converters-SammlungConverters collection
  • Attribut auf TypebeneAttribute on type

Der Unterschied besteht hierbei darin, dass ein benutzerdefinierter Konverter in der Converters-Sammlung ein Attribut auf Typebene außer Kraft setzt.The difference here is that a custom converter in the Converters collection overrides an attribute at the type level. Die Absicht hinter dieser Rangfolge ist es, dass Änderungen zur Laufzeit eine zur Entwurfszeit getroffene Auswahl außer Kraft setzen sollen.The intention behind this order of precedence is to make run-time changes override design-time choices. Diese Rangfolge lässt sich nicht ändern.There's no way to change the precedence.

Weitere Informationen zur Registrierung benutzerdefinierter Konverter finden Sie unter Registrieren eines benutzerdefinierten Konverters.For more information about custom converter registration, see Register a custom converter.

Maximale TiefeMaximum depth

Newtonsoft.Json besitzt kein standardmäßiges Limit für die maximale Tiefe.Newtonsoft.Json doesn't have a maximum depth limit by default. Für System.Text.Json gibt es ein Standardlimit von 64, das sich durch Festlegen von JsonSerializerOptions.MaxDepth konfigurieren lässt.For System.Text.Json there's a default limit of 64, and it's configurable by setting JsonSerializerOptions.MaxDepth.

Wenn Sie System.Text.Json indirekt durch ASP.NET Core verwenden, beträgt die Obergrenze für die maximale Tiefe standardmäßig 32.If you're using System.Text.Json indirectly by using ASP.NET Core, the default maximum depth limit is 32. Der Standardwert ist der gleiche wie bei Modellbindung und wird in der JsonOptions-Klasse festgelegt.The default value is the same as for model binding and is set in the JsonOptions class.

JSON-Zeichenfolgen (Eigenschaftsnamen und Zeichenfolgenwerte)JSON strings (property names and string values)

Während der Deserialisierung akzeptiert Newtonsoft.Json Eigenschaftsnamen, die in doppelten oder einfachen Anführungszeichen stehen oder gar keine Anführungszeichen aufweisen.During deserialization, Newtonsoft.Json accepts property names surrounded by double quotes, single quotes, or without quotes. Es akzeptiert Zeichenfolgenwerte, die in doppelten oder einfachen Anführungszeichen stehen.It accepts string values surrounded by double quotes or single quotes. Newtonsoft.Json akzeptiert beispielsweise folgendes JSON:For example, Newtonsoft.Json accepts the following 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.System.Text.Json only accepts property names and string values in double quotes because that format is required by the RFC 8259 specification and is the only format considered valid JSON.

Ein in einfache Anführungszeichen eingeschlossener Wert führt zu einer JsonException mit folgender Meldung:A value enclosed in single quotes results in a JsonException with the following message:

''' is an invalid start of a value.

Werte, die keine Zeichenfolgen sind, für ZeichenfolgeneigenschaftenNon-string values for string properties

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).Newtonsoft.Json accepts non-string values, such as a number or the literals true and false, for deserialization to properties of type string. Im Folgenden finden Sie ein JSON-Beispiel, das Newtonsoft.Json erfolgreich in die folgende Klasse deserialisiert:Here's an example of JSON that Newtonsoft.Json successfully deserializes to the following class:

{
  "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.System.Text.Json doesn't deserialize non-string values into string properties. Ein für ein Zeichenfolgenfeld empfangener Wert, der keine Zeichenfolge ist, führt zu einer JsonException mit folgender Meldung:A non-string value received for a string field results in a JsonException with the following message:

The JSON value could not be converted to System.String.

Szenarien, die JsonSerializer verwenden und Problemumgehungen erfordernScenarios using JsonSerializer that require workarounds

Die folgenden Szenarien werden von der integrierten Funktionalität nicht unterstützt, aber es sind Problemumgehungen möglich.The following scenarios aren't supported by built-in functionality, but workarounds are possible. Die Problemumgehungen sind benutzerdefinierte Konverter, die möglicherweise keine vollständige Parität mit der Newtonsoft.Json-Funktionalität bereitstellen.The workarounds are custom converters, which may not provide complete parity with Newtonsoft.Json functionality. Für einige davon wird Beispielcode als Beispiele bereitgestellt.For some of these, sample code is provided as examples. Wenn Sie von diesen Newtonsoft.Json-Funktionen abhängig sind, erfordert die Migration Änderungen an Ihren .NET-Objektmodellen oder andere Codeänderungen.If you rely on these Newtonsoft.Json features, migration will require modifications to your .NET object models or other code changes.

Typen ohne integrierte UnterstützungTypes without built-in support

System.Text.Json bietet für die folgenden Typen keine integrierte Unterstützung:System.Text.Json doesn't provide built-in support for the following types:

Benutzerdefinierte Konverter können für Typen implementiert werden, für die keine integrierte Unterstützung vorhanden ist.Custom converters can be implemented for types that don't have built-in support.

Zahlen in AnführungszeichenQuoted numbers

Newtonsoft.Json kann Zahlen serialisieren oder deserialisieren, die von JSON-Zeichenfolgen (in Anführungszeichen) dargestellt werden.Newtonsoft.Json can serialize or deserialize numbers represented by JSON strings (surrounded by quotes). Beispielsweise kann es {"DegreesCelsius":"23"} akzeptieren, anstelle von {"DegreesCelsius":23}.For example, it can accept: {"DegreesCelsius":"23"} instead of {"DegreesCelsius":23}. Um dieses Verhalten in System.Text.Json zu aktivieren, implementieren Sie einen benutzerdefinierten Konverter, wie im folgenden Beispiel gezeigt.To enable that behavior in System.Text.Json, implement a custom converter like the following example. Der Konverter verarbeitet als long definierte Eigenschaften:The converter handles properties defined as long:

  • Er serialisiert sie als JSON-Zeichenfolgen.It serializes them as JSON strings.
  • Er akzeptiert während der Deserialisierung JSON-Zahlen und Zahlen in Anführungszeichen.It accepts JSON numbers and numbers within quotes while deserializing.
using System;
using System.Buffers;
using System.Buffers.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace SystemTextJsonSamples
{
    public class LongToStringConverter : JsonConverter<long>
    {
        public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.String)
            {
                ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
                if (Utf8Parser.TryParse(span, out long number, out int bytesConsumed) && span.Length == bytesConsumed)
                    return number;

                if (Int64.TryParse(reader.GetString(), out number))
                    return number;
            }

            return reader.GetInt64();
        }

        public override void Write(Utf8JsonWriter writer, long longValue, JsonSerializerOptions options)
        {
            writer.WriteStringValue(longValue.ToString());
        }
    }
}

Registrieren Sie diesen benutzerdefinierten Konverter mithilfe eines Attributs für einzelne long-Eigenschaften oder durch Hinzufügen des Konverters zur Converters-Sammlung.Register this custom converter by using an attribute on individual long properties or by adding the converter to the Converters collection.

Wörterbuch mit Schlüssel, der keine Zeichenfolgen istDictionary with non-string key

Newtonsoft.Json unterstützt Sammlungen vom Typ Dictionary<TKey, TValue>.Newtonsoft.Json supports collections of type Dictionary<TKey, TValue>. Die integrierte Unterstützung für Wörterbuchsammlungen in System.Text.Json ist auf Dictionary<string, TValue> beschränkt.The built-in support for dictionary collections in System.Text.Json is limited to Dictionary<string, TValue>. Das heißt, der Schlüssel muss eine Zeichenfolge sein.That is, the key must be a string.

Um ein Wörterbuch mit einem Schlüssel vom Typ „integer“ (Ganzzahl) oder einem anderen Typ zu unterstützen, erstellen Sie einen Konverter wie das Beispiel in Schreiben von benutzerdefinierten Konvertern.To support a dictionary with an integer or some other type as the key, create a converter like the example in How to write custom converters.

Polymorphe SerialisierungPolymorphic serialization

Newtonsoft.Json führt automatisch eine polymorphe Serialisierung durch.Newtonsoft.Json automatically does polymorphic serialization. Informationen zu den eingeschränkten polymorphen Serialisierungsfunktionen von System.Text.Json finden Sie unter Serialisieren von Eigenschaften abgeleiteter Klassen.For information about the limited polymorphic serialization capabilities of System.Text.Json, see Serialize properties of derived classes.

Die dort beschriebene Problemumgehung besteht darin, Eigenschaften zu definieren, die abgeleitete Klassen als object-Typ enthalten können.The workaround described there is to define properties that may contain derived classes as type object. Wenn dies nicht möglich ist, besteht eine weitere Möglichkeit darin, einen Konverter mit einer Write-Methode für die gesamte Vererbungstyphierarchie zu erstellen, wie im Beispiel in Schreiben von benutzerdefinierten Konvertern gezeigt.If that isn't possible, another option is to create a converter with a Write method for the whole inheritance type hierarchy like the example in How to write custom converters.

Polymorphe DeserialisierungPolymorphic deserialization

Newtonsoft.Json verfügt über eine TypeNameHandling-Einstellung, mit der dem JSON-Code beim Serialisieren Typnamen-Metadaten hinzugefügt werden.Newtonsoft.Json has a TypeNameHandling setting that adds type name metadata to the JSON while serializing. Sie verwendet die Metadaten während der Deserialisierung, um die polymorphe Deserialisierung durchzuführen.It uses the metadata while deserializing to do polymorphic deserialization. System.Text.Json kann in einem begrenzten Bereich polymorphe Serialisierung durchführen, aber keine polymorphe Deserialisierung.System.Text.Json can do a limited range of polymorphic serialization but not polymorphic deserialization.

Um polymorphe Deserialisierung zu unterstützen, erstellen Sie einen Konverter wie das Beispiel in Schreiben von benutzerdefinierten Konvertern.To support polymorphic deserialization, create a converter like the example in How to write custom converters.

Deserialisierung von ObjekteigenschaftenDeserialization of object properties

Wenn Newtonsoft.Json in Object deserialisieren, wird Folgendes ausgeführt:When Newtonsoft.Json deserializes to Object, it:

  • Es leitet den Typ primitiver Werte in der JSON-Nutzlast (außer null) ab und gibt die gespeicherten Typen string, long, double, boolean oder DateTime als geschachteltes Objekt zurück.Infers the type of primitive values in the JSON payload (other than null) and returns the stored string, long, double, boolean, or DateTime as a boxed object. Primitive Werte sind einzelne JSON-Werte, wie eine JSON-Zahl, -Zeichenfolge, true, false oder null.Primitive values are single JSON values such as a JSON number, string, true, false, or null.
  • Gibt ein JObject oder JArray für komplexe Werte in der JSON-Nutzlast zurück.Returns a JObject or JArray for complex values in the JSON payload. Komplexe Werte sind Sammlungen von JSON-Schlüssel-Wert-Paaren in geschweiften Klammern ({}) oder Listen mit Werten in eckigen Klammern ([]).Complex values are collections of JSON key-value pairs within braces ({}) or lists of values within brackets ([]). Die Eigenschaften und Werte in geschweiften oder eckigen Klammern können zusätzliche Eigenschaften oder Werte besitzen.The properties and values within the braces or brackets can have additional properties or values.
  • Gibt einen Nullverweis zurück, wenn die Nutzlast das JSON-Literal null enthält.Returns a null reference when the payload has the null JSON literal.

System.Text.Json speichert bei der Deserialisierung in Object ein geschachteltes JsonElement sowohl für primitive als auch für komplexe Werte, z. B.:System.Text.Json stores a boxed JsonElement for both primitive and complex values whenever deserializing to Object, for example:

  • Eine object-Eigenschaft.An object property.
  • Ein object-Wörterbuchwert.An object dictionary value.
  • Ein object-Arraywert.An object array value.
  • Ein Stamm-object.A root 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.However, System.Text.Json treats null the same as Newtonsoft.Json and returns a null reference when the payload has the null JSON literal in it.

Um Typrückschlüsse für object-Eigenschaften zu implementieren, erstellen Sie einen Konverter wie in Schreiben von benutzerdefinierten Konvertern.To implement type inference for object properties, create a converter like the example in How to write custom converters.

Deserialisieren eines Null-Typs in einen Non-Nullable-TypDeserialize null to non-nullable type

Newtonsoft.Json löst im folgenden Szenario keine Ausnahme aus:Newtonsoft.Json doesn't throw an exception in the following scenario:

  • NullValueHandling ist auf Ignore festgelegt, undNullValueHandling is set to Ignore, and
  • Während der Deserialisierung enthält JSON einen Nullwert für einen Non-Nullable-Werttyp.During deserialization, the JSON contains a null value for a non-nullable value type.

Im selben Szenario löst System.Text.Json eine Ausnahme aus.In the same scenario, System.Text.Json does throw an exception. (Die entsprechende Einstellung für die Behandlung von Null ist JsonSerializerOptions.IgnoreNullValues.)(The corresponding null handling setting is JsonSerializerOptions.IgnoreNullValues.)

Wenn Sie den Zieltyp besitzen, besteht die beste Problemumgehung darin, die betreffende Eigenschaft „nullable“ zu machen (z. B. int in int? ändern).If you own the target type, the best workaround is to make the property in question nullable (for example, change int to int?).

Eine weitere Problemumgehung besteht darin, einen Konverter für den Typ zu erstellen, wie im folgenden Beispiel, das Nullwerte für DateTimeOffset-Typen behandelt:Another workaround is to make a converter for the type, such as the following example that handles null values for DateTimeOffset types:

using System;
using System.Globalization;
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)
        {
            if (reader.TokenType == JsonTokenType.Null)
            {
                return default;
            }
            return 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.Register this custom converter by using an attribute on the property or by adding the converter to the Converters collection.

Hinweis: Der vorherige Konverter behandelt Nullwerte anders, als dies Newtonsoft.Json für POCOS tut, die Standardwerte angeben.Note: The preceding converter handles null values differently than Newtonsoft.Json does for POCOs that specify default values. Angenommen, der folgende Code stellt Ihr Zielobjekt dar:For example, suppose the following code represents your target object:

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:And suppose the following JSON is deserialized by using the preceding converter:

{
  "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.After deserialization, the Date property has 1/1/0001 (default(DateTimeOffset)), that is, the value set in the constructor is overwritten. Beim selben POCO und JSON-Code würde die Deserialisierung mit Newtonsoft.Json den Wert „1/1/2001“ in der Date-Eigenschaft belassen.Given the same POCO and JSON, Newtonsoft.Json deserialization would leave 1/1/2001 in the Date property.

Deserialisieren in unveränderliche Klassen und StrukturenDeserialize to immutable classes and structs

Newtonsoft.Json kann in unveränderliche Klassen und Strukturen deserialisieren, weil es Konstruktoren verwenden kann, die Parameter besitzen.Newtonsoft.Json can deserialize to immutable classes and structs because it can use constructors that have parameters. System.Text.Json unterstützt nur öffentliche parameterlose Konstruktoren.System.Text.Json supports only public parameterless constructors. Als Problemumgehung können Sie einen Konstruktor mit Parametern in einem benutzerdefinierten Konverter aufrufen.As a workaround, you can call a constructor with parameters in a custom converter.

Im Folgenden finden Sie eine unveränderliche Struktur mit mehreren Konstruktorparametern:Here's an immutable struct with multiple constructor parameters:

public readonly struct ImmutablePoint
{
    public ImmutablePoint(int x, int y)
    {
        X = x;
        Y = y;
    }

    public int X { get; }
    public int Y { get; }
}

Und hier sehen Sie einen Konverter, der diese Struktur serialisiert und deserialisiert:And here's a converter that serializes and deserializes this struct:

using System;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace SystemTextJsonSamples
{
    public class ImmutablePointConverter : JsonConverter<ImmutablePoint>
    {
        private readonly JsonEncodedText XName = JsonEncodedText.Encode("X");
        private readonly JsonEncodedText YName = JsonEncodedText.Encode("Y");

        private readonly JsonConverter<int> _intConverter;

        public ImmutablePointConverter(JsonSerializerOptions options)
        {
            if (options?.GetConverter(typeof(int)) is JsonConverter<int> intConverter)
            {
                _intConverter = intConverter;
            }
            else
            {
                throw new InvalidOperationException();
            }
        }

        public override ImmutablePoint Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options)
        {
            if (reader.TokenType != JsonTokenType.StartObject)
            {
                throw new JsonException();
            };

            int x = default;
            bool xSet = false;

            int y = default;
            bool ySet = false;

            // Get the first property.
            reader.Read();
            if (reader.TokenType != JsonTokenType.PropertyName)
            {
                throw new JsonException();
            }

            if (reader.ValueTextEquals(XName.EncodedUtf8Bytes))
            {
                x = ReadProperty(ref reader, options);
                xSet = true;
            }
            else if (reader.ValueTextEquals(YName.EncodedUtf8Bytes))
            {
                y = ReadProperty(ref reader, options);
                ySet = true;
            }
            else
            {
                throw new JsonException();
            }

            // Get the second property.
            reader.Read();
            if (reader.TokenType != JsonTokenType.PropertyName)
            {
                throw new JsonException();
            }

            if (xSet && reader.ValueTextEquals(YName.EncodedUtf8Bytes))
            {
                y = ReadProperty(ref reader, options);
            }
            else if (ySet && reader.ValueTextEquals(XName.EncodedUtf8Bytes))
            {
                x = ReadProperty(ref reader, options);
            }
            else
            {
                throw new JsonException();
            }

            reader.Read();

            if (reader.TokenType != JsonTokenType.EndObject)
            {
                throw new JsonException();
            }

            return new ImmutablePoint(x, y);
        }

        private int ReadProperty(ref Utf8JsonReader reader, JsonSerializerOptions options)
        {
            Debug.Assert(reader.TokenType == JsonTokenType.PropertyName);

            reader.Read();
            return _intConverter.Read(ref reader, typeof(int), options);
        }

        private void WriteProperty(Utf8JsonWriter writer, JsonEncodedText name, int intValue, JsonSerializerOptions options)
        {
            writer.WritePropertyName(name);
            _intConverter.Write(writer, intValue, options);
        }

        public override void Write(
            Utf8JsonWriter writer,
            ImmutablePoint point,
            JsonSerializerOptions options)
        {
            writer.WriteStartObject();
            WriteProperty(writer, XName, point.X, options);
            WriteProperty(writer, YName, point.Y, options);
            writer.WriteEndObject();
        }
    }
}

Registrieren Sie diesen benutzerdefinierten Konverter durch Hinzufügen des Konverters zur Converters-Sammlung.Register this custom converter by adding the converter to the Converters collection.

Ein Beispiel für einen ähnlichen Konverter, der offene generische Eigenschaften behandelt, finden Sie unter der Integrierter Konverter für Schlüssel-Wert-Paare.For an example of a similar converter that handles open generic properties, see the built-in converter for key-value pairs.

Angeben des zu verwendenden KonstruktorsSpecify constructor to use

Mit dem [JsonConstructor]-Attribut von Newtonsoft.Json können Sie angeben, welcher Konstruktor beim Deserialisieren in ein POCO aufgerufen werden soll.The Newtonsoft.Json [JsonConstructor] attribute lets you specify which constructor to call when deserializing to a POCO. System.Text.Json unterstützt nur parameterlose Konstruktoren.System.Text.Json supports only parameterless constructors. Als Problemumgehung können Sie einen beliebigen aufrufen, den Sie in einem benutzerdefinierten Konverter benötigen.As a workaround, you can call whichever constructor you need in a custom converter. Siehe das Beispiel für das Deserialisieren in unveränderliche Klassen und Strukturen.See the example for Deserialize to immutable classes and structs.

Erforderliche EigenschaftenRequired properties

In Newtonsoft.Json geben Sie an, dass eine Eigenschaft erforderlich ist, indem Sie Required für das [JsonProperty]-Attribut festlegen.In Newtonsoft.Json, you specify that a property is required by setting Required on the [JsonProperty] attribute. Newtonsoft.Json löst eine Ausnahme aus, wenn im JSON für eine als erforderlich markierte Eigenschaft kein Wert empfangen wird.Newtonsoft.Json throws an exception if no value is received in the JSON for a property marked as required.

System.Text.Json löst keine Ausnahme aus, wenn kein Wert für eine der Eigenschaften des Zieltyps empfangen wird.System.Text.Json doesn't throw an exception if no value is received for one of the properties of the target type. Wenn Sie z. B. eine WeatherForecast-Klasse haben:For example, if you have a WeatherForecast class:

public class WeatherForecast
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}

Der folgende JSON-Code wird ohne Fehler deserialisiert:The following JSON is deserialized without error:

{
    "TemperatureCelsius": 25,
    "Summary": "Hot"
}

Damit die Deserialisierung fehlschlägt, wenn der JSON-Code keine Date-Eigenschaft enthält, implementieren Sie einen benutzerdefinierten Konverter.To make deserialization fail if no Date property is in the JSON, implement a custom converter. Der folgende Beispielcode für einen Konverter löst nach Abschluss der Deserialisierung eine Ausnahme aus, wenn die Date-Eigenschaft nicht festgelegt ist:The following sample converter code throws an exception if the Date property isn't set after deserialization is complete:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace SystemTextJsonSamples
{
    public class WeatherForecastRequiredPropertyConverter : JsonConverter<WeatherForecast>
    {
        public override WeatherForecast Read(
            ref Utf8JsonReader reader,
            Type type,
            JsonSerializerOptions options)
        {
            // Don't pass in options when recursively calling Deserialize.
            WeatherForecast forecast = JsonSerializer.Deserialize<WeatherForecast>(ref reader);

            // Check for required fields set by values in JSON
            if (forecast.Date == default)
            {
                throw new JsonException("Required property not received in the JSON");
            }
            return forecast;
        }

        public override void Write(
            Utf8JsonWriter writer,
            WeatherForecast forecast, JsonSerializerOptions options)
        {
            // Don't pass in options when recursively calling Serialize.
            JsonSerializer.Serialize(writer, forecast);
        }
    }
}

Registrieren Sie diesen benutzerdefinierten Konverter durch Hinzufügen des Konverters zur JsonSerializerOptions.Converters-Sammlung.Register this custom converter by adding the converter to the JsonSerializerOptions.Converters collection.

Für dieses Muster rekursiver Aufrufe des Konverters ist erforderlich, dass Sie den Konverter mit JsonSerializerOptions registrieren, anstatt mithilfe eines Attributs.This pattern of recursively calling the converter requires that you register the converter by using JsonSerializerOptions, not by using an attribute. Wenn Sie den Konverter mithilfe eines Attributs registrieren, ruft der benutzerdefinierte Konverter sich rekursiv selbst auf.If you register the converter by using an attribute, the custom converter recursively calls into itself. Dies resultiert in einer Endlosschleife, die mit einer Stapelüberlaufausnahme endet.The result is an infinite loop that ends in a stack overflow exception.

Wenn Sie den Konverter mithilfe des Optionsobjekts registrieren, vermeiden Sie eine Endlosschleife, indem Sie nicht das Options-Objekt übergeben, wenn Serialize oder Deserialize rekursiv aufgerufen wird.When you register the converter by using the options object, avoid an infinite loop by not passing in the options object when recursively calling Serialize or Deserialize. Das options-Objekt enthält die Converters-Sammlung.The options object contains the Converters collection. Wenn Sie es an Serialize oder Deserialize übergeben, ruft sich der benutzerdefinierte Konverter selbst auf, wodurch eine Endlosschleife entsteht, die zu einer Stapelüberlaufausnahme führt.If you pass it in to Serialize or Deserialize, the custom converter calls into itself, making an infinite loop that results in a stack overflow exception. Wenn die Standardoptionen nicht praktikabel sind, erstellen Sie eine neue Instanz der Optionen mit den Einstellungen, die Sie benötigen.If the default options are not feasible, create a new instance of the options with the settings that you need. Diese Vorgehensweise ist langsam, da jede neue Instanz unabhängig zwischengespeichert wird.This approach will be slow since each new instance caches independently.

Es gibt ein alternatives Muster, dass die JsonConverterAttribute-Registrierung für die zu konvertierende Klasse verwenden kann.There is an alternative pattern that can use JsonConverterAttribute registration on the class to be converted. Bei diesem Ansatz ruft der Code des Konverters Serialize oder Deserialize für eine Klasse auf, die von der zu konvertierenden Klasse abgeleitet wird.In this approach, the converter code calls Serialize or Deserialize on a class that derives from the class to be converted. JsonConverterAttribute wird nicht auf die abgeleitete Klasse angewendet.The derived class doesn't have a JsonConverterAttribute applied to it. Im folgenden Beispiel dieser Alternative:In the following example of this alternative:

  • ist WeatherForecastWithRequiredPropertyConverterAttribute die zu deserialisierende Klasse, und JsonConverterAttribute wurde auf diese angewendet.WeatherForecastWithRequiredPropertyConverterAttribute is the class to be deserialized and has the JsonConverterAttribute applied to it.
  • ist WeatherForecastWithoutRequiredPropertyConverterAttribute die abgeleitete Klasse, die das Konverterattribut nicht aufweist.WeatherForecastWithoutRequiredPropertyConverterAttribute is the derived class that doesn't have the converter attribute.
  • Der Code im Konverter ruft Serialize und Deserialize für WeatherForecastWithoutRequiredPropertyConverterAttribute auf, um eine Endlosschleife zu vermeiden.The code in the converter calls Serializeand Deserialize on WeatherForecastWithoutRequiredPropertyConverterAttribute to avoid an infinite loop. Bei diesem Serialisierungsansatz kommt es zu Leistungseinbußen, da eine zusätzliche Objektinstanziierung und Kopien von Eigenschaftswerten vorgenommen werden.There is a performance cost to this approach on serialization due to an extra object instantiation and copying of property values.

Im Folgenden werden die WeatherForecast*-Typen veranschaulicht:Here are the WeatherForecast* types:

[JsonConverter(typeof(WeatherForecastRequiredPropertyConverterForAttributeRegistration))]
public class WeatherForecastWithRequiredPropertyConverterAttribute
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}

public class WeatherForecastWithoutRequiredPropertyConverterAttribute : WeatherForecastWithRequiredPropertyConverterAttribute
{
}

So sieht der Konverter aus:And here is the converter:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace SystemTextJsonSamples
{
    public class WeatherForecastRequiredPropertyConverterForAttributeRegistration : 
        JsonConverter<WeatherForecastWithRequiredPropertyConverterAttribute>
    {
        public override WeatherForecastWithRequiredPropertyConverterAttribute Read(
            ref Utf8JsonReader reader,
            Type type,
            JsonSerializerOptions options)
        {
            // OK to pass in options when recursively calling Deserialize.
            WeatherForecastWithRequiredPropertyConverterAttribute forecast = 
                JsonSerializer.Deserialize<WeatherForecastWithoutRequiredPropertyConverterAttribute>(
                    ref reader, 
                    options);

            // Check for required fields set by values in JSON.
            if (forecast.Date == default)
            {
                throw new JsonException("Required property not received in the JSON");
            }

            return forecast;
        }

        public override void Write(
            Utf8JsonWriter writer,
            WeatherForecastWithRequiredPropertyConverterAttribute forecast, 
            JsonSerializerOptions options)
        {
            var weatherForecastWithoutConverterAttributeOnClass = 
                new WeatherForecastWithoutRequiredPropertyConverterAttribute
            {
                Date = forecast.Date,
                TemperatureCelsius = forecast.TemperatureCelsius,
                Summary = forecast.Summary
            };

            // OK to pass in options when recursively calling Serialize.
            JsonSerializer.Serialize(
                writer, 
                weatherForecastWithoutConverterAttributeOnClass, 
                options);
        }
    }
}

Der erforderliche Eigenschaftenkonverter würde zusätzliche Logik erfordern, wenn Sie Attribute wie [JsonIgnore] oder verschiedene Optionen wie benutzerdefinierte Encoder verarbeiten müssten.The required properties converter would require additional logic if you need to handle attributes such as [JsonIgnore] or different options, such as custom encoders. Der Beispielcode verarbeitet außerdem keine Eigenschaften, für die im Konstruktor ein Standardwert festgelegt ist.Also, the example code doesn't handle properties for which a default value is set in the constructor. Und dieser Ansatz unterscheidet nicht zwischen den folgenden Szenarien:And this approach doesn't differentiate between the following scenarios:

  • Im JSON fehlt eine Eigenschaft.A property is missing from the JSON.
  • Im JSON ist eine Eigenschaft für einen Non-Nullable-Typ vorhanden, aber der Wert ist der Standardwert für den Typ, z. B. Null für einen int.A property for a non-nullable type is present in the JSON, but the value is the default for the type, such as zero for an int.
  • Im JSON ist eine Eigenschaft für einen Nullable-Werttyp vorhanden, aber der Wert ist Null.A property for a nullable value type is present in the JSON, but the value is null.

Bedingtes Ignorieren einer EigenschaftConditionally ignore a property

Newtonsoft.Json bietet mehrere Möglichkeiten, um eine Eigenschaft bei der Serialisierung oder Deserialisierung bedingt zu ignorieren:Newtonsoft.Json has several ways to conditionally ignore a property on serialization or deserialization:

  • DefaultContractResolver ermöglicht das Auswählen von Eigenschaften, die eingeschlossen oder ausgeschlossen werden sollen, basierend auf beliebigen Kriterien.DefaultContractResolver lets you select properties to include or exclude, based on arbitrary criteria.
  • Mit den Einstellungen NullValueHandling und DefaultValueHandling von JsonSerializerSettings können Sie angeben, dass alle Eigenschaften mit Nullwert oder Standardwert ignoriert werden sollen.The NullValueHandling and DefaultValueHandling settings on JsonSerializerSettings let you specify that all null-value or default-value properties should be ignored.
  • Mit den Einstellungen NullValueHandling und DefaultValueHandling des [JsonProperty]-Attributs können Sie einzelne Eigenschaften angeben, die ignoriert werden sollen, wenn Sie auf Null oder den Standardwert festgelegt sind.The NullValueHandling and DefaultValueHandling settings on the [JsonProperty] attribute let you specify individual properties that should be ignored when set to null or the default value.

System.Text.Json bietet die folgenden Möglichkeiten, um während der Serialisierung Eigenschaften auszulassen:System.Text.Json provides the following ways to omit properties while serializing:

  • Das [JsonIgnore]-Attribut einer Eigenschaft bewirkt, dass die Eigenschaft während der Serialisierung im JSON-Code ausgelassen wird.The [JsonIgnore] attribute on a property causes the property to be omitted from the JSON during serialization.
  • Mit der globalen Option IgnoreNullValues können Sie alle Eigenschaften mit Nullwert ausschließen.The IgnoreNullValues global option lets you exclude all null-value properties.
  • Mit der globalen Option IgnoreReadOnlyProperties können Sie alle schreibgeschützten Eigenschaften ausschließen.The IgnoreReadOnlyProperties global option lets you exclude all read-only properties.

Diese Optionen gestatten Ihnen Folgendes nicht:These options don't let you:

  • Ignorieren aller Eigenschaften, die den Standardwert für den Typ aufweisen.Ignore all properties that have the default value for the type.
  • Ignorieren ausgewählter Eigenschaften, die den Standardwert für den Typ aufweisen.Ignore selected properties that have the default value for the type.
  • Ignorieren ausgewählter Eigenschaften, wenn deren Wert Null ist.Ignore selected properties if their value is null.
  • Ignorieren ausgewählter Eigenschaften auf Grundlage beliebiger Kriterien, die zur Laufzeit ausgewertet werden.Ignore selected properties based on arbitrary criteria evaluated at run time.

Für diese Funktionalität können Sie einen benutzerdefinierten Konverter schreiben.For that functionality, you can write a custom converter. Im Folgenden finden Sie ein Beispiel-POCO und einen benutzerdefinierten Konverter dafür, um diesen Ansatz zu veranschaulichen:Here's a sample POCO and a custom converter for it that illustrates this approach:

public class WeatherForecast
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string Summary { get; set; }
}
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace SystemTextJsonSamples
{
    public class WeatherForecastRuntimeIgnoreConverter : JsonConverter<WeatherForecast>
    {
        public override WeatherForecast Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options)
        {
            if (reader.TokenType != JsonTokenType.StartObject)
            {
                throw new JsonException();
            }

            var wf = new WeatherForecast();

            while (reader.Read())
            {
                if (reader.TokenType == JsonTokenType.EndObject)
                {
                    return wf;
                }

                if (reader.TokenType == JsonTokenType.PropertyName)
                {
                    string propertyName = reader.GetString();
                    reader.Read();
                    switch (propertyName)
                    {
                        case "Date":
                            DateTimeOffset date = reader.GetDateTimeOffset();
                            wf.Date = date;
                            break;
                        case "TemperatureCelsius":
                            int temperatureCelsius = reader.GetInt32();
                            wf.TemperatureCelsius = temperatureCelsius;
                            break;
                        case "Summary":
                            string summary = reader.GetString();
                            wf.Summary = string.IsNullOrWhiteSpace(summary) ? "N/A" : summary;
                            break;
                    }
                }
            }

            throw new JsonException();
        }

        public override void Write(Utf8JsonWriter writer, WeatherForecast wf, JsonSerializerOptions options)
        {
            writer.WriteStartObject();

            writer.WriteString("Date", wf.Date);
            writer.WriteNumber("TemperatureCelsius", wf.TemperatureCelsius);
            if (!string.IsNullOrWhiteSpace(wf.Summary) && wf.Summary != "N/A")
            {
                writer.WriteString("Summary", wf.Summary);
            }

            writer.WriteEndObject();
        }
    }
}

Der Konverter bewirkt, dass die Summary-Eigenschaft bei der Serialisierung ausgelassen wird, wenn ihr Wert Null, eine leere Zeichenfolge oder „N/V“ ist.The converter causes the Summary property to be omitted from serialization if its value is null, an empty string, or "N/A".

Registrieren Sie diesen benutzerdefinierten Konverter mithilfe eines Attributs für die Klasse oder durch Hinzufügen des Konverters zur Converters-Sammlung.Register this custom converter by using an attribute on the class or by adding the converter to the Converters collection.

Für diesen Ansatz ist zusätzliche Logik erforderlich, wenn:This approach requires additional logic if:

  • Das POCO komplexe Eigenschaften enthält.The POCO includes complex properties.
  • Sie Attribute wie [JsonIgnore] oder Optionen wie benutzerdefinierte Encoder verarbeiten müssen.You need to handle attributes such as [JsonIgnore] or options such as custom encoders.

Angeben des DatumsformatsSpecify date format

Newtonsoft.Json bietet verschiedene Möglichkeiten, um zu kontrollieren, wie Eigenschaften des Typs DateTime und DateTimeOffset serialisiert und deserialisiert werden:Newtonsoft.Json provides several ways to control how properties of DateTime and DateTimeOffset types are serialized and deserialized:

  • Die DateTimeZoneHandling-Einstellung kann verwendet werden, um alle DateTime-Werte als UTC-Datumsangaben zu serialisieren.The DateTimeZoneHandling setting can be used to serialize all DateTime values as UTC dates.
  • Die DateFormatString-Einstellung und DateTime-Konverter können verwendet werden, um das Format von Datumszeichenfolgen anzupassen.The DateFormatString setting and DateTime converters can be used to customize the format of date strings.

In System.Text.Json ist das einzige Format, das über integrierte Unterstützung verfügt, ISO 8601-1:2019, da es weit verbreitet und eindeutig ist und Roundtrips exakt gestaltet.In System.Text.Json, the only format that has built-in support is ISO 8601-1:2019 since it's widely adopted, unambiguous, and makes round trips precisely. Um ein beliebiges anderes Format zu verwenden, erstellen Sie einen benutzerdefinierten Konverter.To use any other format, create a custom converter. Weitere Informationen finden Sie unter Unterstützung von „DateTime“ und „DateTimeOffset“ in System.Text.Json.For more information, see DateTime and DateTimeOffset support in System.Text.Json.

RückrufeCallbacks

Newtonsoft.Json ermöglicht das Ausführen von benutzerdefiniertem Code an mehreren Stellen im Serialisierungs- oder Deserialisierungsprozess:Newtonsoft.Json lets you execute custom code at several points in the serialization or deserialization process:

  • OnDeserializing (bei Beginn der Deserialisierung eines Objekts)OnDeserializing (when beginning to deserialize an object)
  • OnDeserialized (nach Abschluss der Deserialisierung eines Objekts)OnDeserialized (when finished deserializing an object)
  • OnSerializing (bei Beginn der Serialisierung eines Objekts)OnSerializing (when beginning to serialize an object)
  • OnSerialized (nach Abschluss der Serialisierung eines Objekts)OnSerialized (when finished serializing an object)

In System.Text.Json können Sie Rückrufe simulieren, indem Sie einen benutzerdefinierten Konverter schreiben.In System.Text.Json, you can simulate callbacks by writing a custom converter. Im folgenden Beispiel wird ein benutzerdefinierter Konverter für ein POCO gezeigt.The following example shows a custom converter for a POCO. Der Konverter enthält Code, der an jeder Stelle eine Meldung anzeigt, die einem Newtonsoft.Json-Rückruf entspricht.The converter includes code that displays a message at each point that corresponds to a Newtonsoft.Json callback.

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace SystemTextJsonSamples
{
    public class WeatherForecastCallbacksConverter : JsonConverter<WeatherForecast>
    {
        public override WeatherForecast Read(
            ref Utf8JsonReader reader,
            Type type,
            JsonSerializerOptions options)
        {
            // Place "before" code here (OnDeserializing),
            // but note that there is no access here to the POCO instance.
            Console.WriteLine("OnDeserializing");

            // Don't pass in options when recursively calling Deserialize.
            WeatherForecast forecast = JsonSerializer.Deserialize<WeatherForecast>(ref reader);

            // Place "after" code here (OnDeserialized)
            Console.WriteLine("OnDeserialized");

            return forecast;
        }

        public override void Write(
            Utf8JsonWriter writer,
            WeatherForecast forecast, JsonSerializerOptions options)
        {
            // Place "before" code here (OnSerializing)
            Console.WriteLine("OnSerializing");

            // Don't pass in options when recursively calling Serialize.
            JsonSerializer.Serialize(writer, forecast);

            // Place "after" code here (OnSerialized)
            Console.WriteLine("OnSerialized");
        }
    }
}

Registrieren Sie diesen benutzerdefinierten Konverter durch Hinzufügen des Konverters zur Converters-Sammlung.Register this custom converter by adding the converter to the Converters collection.

Wenn Sie einen benutzerdefinierten Konverter verwenden, der sich am vorangehenden Beispiel orientiert:If you use a custom converter that follows the preceding sample:

  • Der OnDeserializing-Code hat keinen Zugriff auf die neue POCO-Instanz.The OnDeserializing code doesn't have access to the new POCO instance. Um die neue POCO-Instanz zu Beginn der Deserialisierung zu bearbeiten, fügen Sie diesen Code in den POCO-Konstruktor ein.To manipulate the new POCO instance at the start of deserialization, put that code in the POCO constructor.
  • Vermeiden Sie eine Endlosschleife, indem Sie den Konverter im Options-Objekt registrieren und dieses nicht übergeben, wenn Serialize oder Deserialize rekursiv aufgerufen wird.Avoid an infinite loop by registering the converter in the options object and not passing in the options object when recursively calling Serialize or Deserialize.

Weitere Informationen zu benutzerdefinierten Konvertern, dieSerialize oder Deserialize rekursiv aufrufen, finden Sie unter Erforderliche Eigenschaften weiter oben in diesem Artikel.For more information about custom converters that recursively call Serialize or Deserialize, see the Required properties section earlier in this article.

Öffentliche und nicht öffentliche FelderPublic and non-public fields

Newtonsoft.Json kann Felder ebenso wie Eigenschaften serialisieren und deserialisieren.Newtonsoft.Json can serialize and deserialize fields as well as properties. System.Text.Json funktioniert nur mit öffentlichen Eigenschaften.System.Text.Json only works with public properties. Benutzerdefinierte Konverter können diese Funktionalität bereitstellen.Custom converters can provide this functionality.

Interne und private Eigenschaften-Setter und -GetterInternal and private property setters and getters

Newtonsoft.Json kann private und interne Eigenschaften-Setter und -Getter über das JsonProperty-Attribut verwenden.Newtonsoft.Json can use private and internal property setters and getters via the JsonProperty attribute. System.Text.Json unterstützt nur öffentliche Setter.System.Text.Json supports only public setters. Benutzerdefinierte Konverter können diese Funktionalität bereitstellen.Custom converters can provide this functionality.

Auffüllen vorhandener ObjektePopulate existing objects

Die JsonConvert.PopulateObject-Methode in Newtonsoft.Json deserialisiert ein JSON-Dokument in eine vorhandene Instanz einer Klasse, anstatt eine neue Instanz zu erstellen.The JsonConvert.PopulateObject method in Newtonsoft.Json deserializes a JSON document to an existing instance of a class, instead of creating a new instance. System.Text.Json erstellt immer eine neue Instanz des Zieltyps unter Verwendung des standardmäßigen öffentlichen parameterlosen Konstruktors.System.Text.Json always creates a new instance of the target type by using the default public parameterless constructor. Benutzerdefinierte Konverter können in eine vorhandene Instanz deserialisieren.Custom converters can deserialize to an existing instance.

Wiederverwenden statt Ersetzen von EigenschaftenReuse rather than replace properties

Mit der Einstellung Newtonsoft.Json ObjectCreationHandling können Sie angeben, dass Objekte in Eigenschaften wiederverwendet werden sollen, anstatt während der Deserialisierung ersetzt zu werden.The Newtonsoft.Json ObjectCreationHandling setting lets you specify that objects in properties should be reused rather than replaced during deserialization. System.Text.Json ersetzt Objekte in Eigenschaften immer.System.Text.Json always replaces objects in properties. Benutzerdefinierte Konverter können diese Funktionalität bereitstellen.Custom converters can provide this functionality.

Hinzufügen zu Sammlungen ohne SetterAdd to collections without setters

Während der Deserialisierung fügt Newtonsoft.Json einer Sammlung Objekte hinzu, auch wenn die Eigenschaft über keinen Setter verfügt.During deserialization, Newtonsoft.Json adds objects to a collection even if the property has no setter. System.Text.Json ignoriert Eigenschaften, die keinen Setter besitzen.System.Text.Json ignores properties that don't have setters. Benutzerdefinierte Konverter können diese Funktionalität bereitstellen.Custom converters can provide this functionality.

Zurzeit von JsonSerializer nicht unterstützte SzenarienScenarios that JsonSerializer currently doesn't support

Für die folgenden Szenarien sind Problemumgehungen nicht praktikabel oder möglich.For the following scenarios, workarounds are not practical or possible. Wenn Sie von diesen Newtonsoft.Json-Funktionen abhängig sind, ist die Migration nicht ohne wesentliche Änderungen möglich.If you rely on these Newtonsoft.Json features, migration will not be possible without significant changes.

Erhalten von Objektverweise und Behandeln von SchleifenPreserve object references and handle loops

Standardmäßig serialisiert Newtonsoft.Json als Wert.By default, Newtonsoft.Json serializes by value. 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.For example, if an object contains two properties that contain a reference to the same Person object, the values of that Person object's properties are duplicated in the JSON.

Newtonsoft.Json verfügt über eine PreserveReferencesHandling-Einstellung für JsonSerializerSettings, mit der Sie als Verweis serialisieren können:Newtonsoft.Json has a PreserveReferencesHandling setting on JsonSerializerSettings that lets you serialize by reference:

  • Dem für das erste Person-Objekt erstellten JSON-Code werden Bezeichnermetadaten hinzugefügt.An identifier metadata is added to the JSON created for the first Person object.
  • Der für das zweite Person-Objekt erstellte JSON-Code enthält einen Verweis auf diesen Bezeichner anstelle der Eigenschaftswerte.The JSON that is created for the second Person object contains a reference to that identifier instead of property values.

Newtonsoft.Json verfügt außerdem über eine ReferenceLoopHandling-Einstellung, mit der Sie Zirkelbezüge ignorieren können, anstatt eine Ausnahme auszulösen.Newtonsoft.Json also has a ReferenceLoopHandling setting that lets you ignore circular references rather than throw an exception.

System.Text.Json unterstützt nur die Serialisierung nach Wert und löst für Zirkelbezüge eine Ausnahme aus.System.Text.Json only supports serialization by value and throws an exception for circular references.

System.Runtime.Serialization-AttributeSystem.Runtime.Serialization attributes

System.Text.Json unterstützt keine Attribute aus dem System.Runtime.Serialization-Namespace, z. B. DataMemberAttribute und IgnoreDataMemberAttribute.System.Text.Json doesn't support attributes from the System.Runtime.Serialization namespace, such as DataMemberAttribute and IgnoreDataMemberAttribute.

OktalzahlenOctal numbers

Newtonsoft.Json behandelt Zahlen mit einer führenden Null als Oktalzahlen.Newtonsoft.Json treats numbers with a leading zero as octal numbers. System.Text.Json lässt keine führenden Nullen zu, da sie von der Spezifikation RFC 8259 nicht zugelassen werden.System.Text.Json doesn't allow leading zeroes because the RFC 8259 specification doesn't allow them.

MissingMemberHandlingMissingMemberHandling

Newtonsoft.Json kann so konfiguriert werden, dass während der Deserialisierung Ausnahmen ausgelöst werden, wenn JSON Eigenschaften enthält, die im Zieltyp fehlen.Newtonsoft.Json can be configured to throw exceptions during deserialization if the JSON includes properties that are missing in the target type. System.Text.Json ignoriert zusätzliche Eigenschaften im JSON-Code, außer wenn Sie das Attribut [JsonExtensionData] verwenden.System.Text.Json ignores extra properties in the JSON, except when you use the [JsonExtensionData] attribute. Für die fehlende Member-Funktion gibt es keine Problemumgehung.There's no workaround for the missing member feature.

TraceWriterTraceWriter

Mit Newtonsoft.Json können Sie Debuggen, indem Sie einen TraceWriter verwenden, um Protokolle anzuzeigen, die von der Serialisierung oder Deserialisierung generiert werden.Newtonsoft.Json lets you debug by using a TraceWriter to view logs that are generated by serialization or deserialization. System.Text.Json führt keine Protokollierung aus.System.Text.Json doesn't do logging.

„JsonDocument“ und „JsonElement“ im Vergleich zu „JToken“ (wie „JObject“, „JArray“)JsonDocument and JsonElement compared to JToken (like JObject, JArray)

System.Text.Json.JsonDocument bietet die Möglichkeit, ein schreibgeschütztes Dokumentobjektmodell (DOM) aus vorhandenen JSON-Nutzlasten zu analysieren und zu erstellen.System.Text.Json.JsonDocument provides the ability to parse and build a read-only Document Object Model (DOM) from existing JSON payloads. Das DOM bietet zufälligen Zugriff auf Daten in einer JSON-Nutzlast.The DOM provides random access to data in a JSON payload. Auf die JSON-Elemente, aus denen sich die Nutzlast zusammensetzt, kann über den Typ JsonElement zugegriffen werden.The JSON elements that compose the payload can be accessed via the JsonElement type. Der JsonElement-Typ stellt APIs zum Konvertieren von JSON-Text in allgemeine .NET-Typen bereit.The JsonElement type provides APIs to convert JSON text to common .NET types. JsonDocument macht eine RootElement-Eigenschaft verfügbar.JsonDocument exposes a RootElement property.

„JsonDocument“ ist „IDisposable“JsonDocument is IDisposable

JsonDocument erstellt eine In-Memory-Ansicht der Daten in einem gepoolten Puffer.JsonDocument builds an in-memory view of the data into a pooled buffer. Daher implementiert der JsonDocument-Typ IDisposable, im Gegensatz zu JObject oder JArray von Newtonsoft.Json, und muss innerhalb eines using-Blocks verwendet werden.Therefore, unlike JObject or JArray from Newtonsoft.Json, the JsonDocument type implements IDisposable and needs to be used inside a using block.

Gibt nur ein JsonDocument von ihrer API zurück, wenn Sie den Besitz der Lebensdauer und die Verantwortung für die Entsorgung an den Aufrufer übertragen möchten.Only return a JsonDocument from your API if you want to transfer lifetime ownership and dispose responsibility to the caller. In den meisten Szenarien ist dies nicht erforderlich.In most scenarios, that isn't necessary. Wenn der Aufrufer mit dem gesamten JSON-Dokument arbeiten muss, geben Sie den Clone des RootElement zurück, bei dem es sich um ein JsonElement handelt.If the caller needs to work with the entire JSON document, return the Clone of the RootElement, which is a JsonElement. Wenn der Aufrufer mit einem bestimmten Element innerhalb des JSON-Dokuments arbeiten muss, geben Sie den Clone dieses JsonElement zurück.If the caller needs to work with a particular element within the JSON document, return the Clone of that JsonElement. Wenn Sie das RootElement oder ein Unterelement direkt zurückgeben, ohne einen Clone zu erstellen, kann der Aufrufer nicht auf das zurückgegebene JsonElement zugreifen, nachdem das JsonDocument, das dessen Besitzer ist, entsorgt wurde.If you return the RootElement or a sub-element directly without making a Clone, the caller won't be able to access the returned JsonElement after the JsonDocument that owns it is disposed.

Hier sehen Sie ein Beispiel, in dem Sie einen Clone erstellen müssen:Here's an example that requires you to make a Clone:

public JsonElement LookAndLoad(JsonElement source)
{
    string json = File.ReadAllText(source.GetProperty("fileName").GetString());

    using (JsonDocument doc = JsonDocument.Parse(json))
    {
        return doc.RootElement.Clone();
    }
}

Der vorangehende Code erwartet ein JsonElement, das eine fileName-Eigenschaft enthält.The preceding code expects a JsonElement that contains a fileName property. Er öffnet die JSON-Datei und erstellt ein JsonDocument.It opens the JSON file and creates a JsonDocument. Die Methode setzt voraus, dass der Aufrufer mit dem gesamten Dokument arbeiten möchte, weshalb sie den Clone des RootElement zurückgibt.The method assumes that the caller wants to work with the entire document, so it returns the Clone of the RootElement.

Wenn Sie ein JsonElement erhalten und ein Unterelement zurückgeben, ist es nicht notwendig, einen Clone des Unterelements zurückzugeben.If you receive a JsonElement and are returning a sub-element, it's not necessary to return a Clone of the sub-element. Der Aufrufer ist dafür verantwortlich, das JsonDocument zu erhalten, zu dem das übergebene JsonElement gehört.The caller is responsible for keeping alive the JsonDocument that the passed-in JsonElement belongs to. Zum Beispiel:For example:

public JsonElement ReturnFileName(JsonElement source)
{
   return source.GetProperty("fileName");
}

Das „JsonDocument“ ist schreibgeschützt.JsonDocument is read-only

Das System.Text.Json-DOM kann keine JSON-Elemente hinzufügen, entfernen oder ändern.The System.Text.Json DOM can't add, remove, or modify JSON elements. Es ist auf diese Weise konzipiert, um Leistung zu gewährleisten und Zuordnungen für die Analyse gängiger JSON-Nutzlastgrößen (d. h. <1 MB) zu verringern.It's designed this way for performance and to reduce allocations for parsing common JSON payload sizes (that is, < 1 MB). Wenn Ihr Szenario derzeit ein änderbares DOM verwendet, könnte eine der folgenden Problemumgehungen praktikabel sein:If your scenario currently uses a modifiable DOM, one of the following workarounds might be feasible:

  • Um ein JsonDocument von Grund auf neu zu erstellen (d. h. ohne eine vorhandene JSON-Nutzlast an die Parse-Methode zu übergeben), schreiben Sie den JSON-Text unter Verwendung von Utf8JsonWriter, und analysieren Sie dessen Ausgabe, um ein neues JsonDocument zu erstellen.To build a JsonDocument from scratch (that is, without passing in an existing JSON payload to the Parse method), write the JSON text by using the Utf8JsonWriter and parse the output from that to make a new JsonDocument.
  • Um ein vorhandenes JsonDocument zu ändern, verwenden Sie es, um JSON-Text zu schreiben, wobei Sie währenddessen Änderungen daran vornehmen, und analysieren seine Ausgabe, um daraus ein neues JsonDocument zu erstellen.To modify an existing JsonDocument, use it to write JSON text, making changes while you write, and parse the output from that to make a new JsonDocument.
  • Informationen zum Zusammenführen vorhandener JSON-Dokumente, entsprechend den APIs JObject.Merge oder JContainer.Merge aus Newtonsoft.Json, finden Sie unter diesem GitHub-Issue.To merge existing JSON documents, equivalent to the JObject.Merge or JContainer.Merge APIs from Newtonsoft.Json, see this GitHub issue.

„JsonElement“ ist eine union-StrukturJsonElement is a union struct

JsonDocument macht das RootElement als Eigenschaft des Typs JsonElement verfügbar, wobei es sich um einen union-Strukturtyp handelt, der jedes JSON-Element umfasst.JsonDocument exposes the RootElement as a property of type JsonElement, which is a union, struct type that encompasses any JSON element. Newtonsoft.Json verwendet dedizierte hierarchische Typen wie JObject, JArray, JToken usw.Newtonsoft.Json uses dedicated hierarchical types like JObject,JArray, JToken, and so forth. 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.JsonElement is what you can search and enumerate over, and you can use JsonElement to materialize JSON elements into .NET types.

Durchsuchen eines „JSonDocument“ und „JsonElement“ nach UnterelementenHow to search a JsonDocument and JsonElement for sub-elements

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.Searches for JSON tokens using JObject or JArray from Newtonsoft.Json tend to be relatively fast because they're lookups in some dictionary. Im Vergleich dazu erfordern Suchen im JsonElement eine sequenzielle Suche der Eigenschaften, sodass sie deswegen relativ langsam sind (z. B. bei Verwendung von TryGetProperty).By comparison, searches on JsonElement require a sequential search of the properties and hence is relatively slow (for example when using TryGetProperty). System.Text.Json ist darauf ausgelegt, die anfängliche Analysezeit zu minimieren anstatt die Nachschlagezeit.System.Text.Json is designed to minimize initial parse time rather than lookup time. Verwenden Sie deshalb die folgenden Ansätze, um die Leistung beim Durchsuchen eines JsonDocument-Objekts zu optimieren:Therefore, use the following approaches to optimize performance when searching through a JsonDocument object:

  • Verwenden Sie die integrierten Enumeratoren (EnumerateArray und EnumerateObject), anstatt ihre eigene Indizierung oder eigene Schleifen zu verwenden.Use the built-in enumerators (EnumerateArray and EnumerateObject) rather than doing your own indexing or loops.
  • Führen Sie keine sequenzielle Suche im gesamten JsonDocument durch alle Eigenschaften durch, indem Sie RootElement verwenden.Don't do a sequential search on the whole JsonDocument through every property by using RootElement. Suchen Sie stattdessen in geschachtelten JSON-Objekten, basierend auf der bekannten Struktur der JSON-Daten.Instead, search on nested JSON objects based on the known structure of the JSON data. Wenn Sie z. B. nach einer Grade-Eigenschaft in Student-Objekten suchen, durchlaufen Sie die Student-Objekte per Schleife, und rufen Sie den Wert von Grade für jedes ab, anstatt auf der Suche nach Grade-Eigenschaften alle JsonElement-Objekte zu durchsuchen.For example, if you're looking for a Grade property in Student objects, loop through the Student objects and get the value of Grade for each, rather than searching through all JsonElement objects looking for Grade properties. Die letztgenannte Vorgehensweise führt zu unnötigen Durchläufen sämtlicher Daten.Doing the latter will result in unnecessary passes over the same data.

Ein Codebeispiel finden Sie unter Verwenden von „JsonDocument“ für den Zugriff auf Daten.For a code example, see Use JsonDocument for access to data.

„Utf8JsonReader“ im Vergleich zu „JsonTextReader“Utf8JsonReader compared to JsonTextReader

System.Text.Json.Utf8JsonReader ist ein leistungsstarker, rein vorwärtsgerichteter Reader mit geringer Zuordnung für UTF-8-codierten JSON-Text, der aus ReadOnlySpan<byte> oder ReadOnlySequence<byte> gelesen wird.System.Text.Json.Utf8JsonReader is a high-performance, low allocation, forward-only reader for UTF-8 encoded JSON text, read from a ReadOnlySpan<byte> or ReadOnlySequence<byte>. Der Utf8JsonReader ist ein Low-Level-Typ, der zum Erstellen von benutzerdefinierten Parsern und Deserialisierungsprogrammen genutzt werden kann.The Utf8JsonReader is a low-level type that can be used to build custom parsers and deserializers.

In den folgenden Abschnitten werden empfohlene Programmiermuster für die Verwendung von Utf8JsonReader erläutert.The following sections explain recommended programming patterns for using Utf8JsonReader.

„Utf8JsonReader“ ist eine ref-Struktur.Utf8JsonReader is a ref struct

Da der Utf8JsonReader-Typ eine ref-Struktur ist, unterliegt er bestimmten Einschränkungen.Because the Utf8JsonReader type is a ref struct, it has certain limitations. Beispielsweise kann er nicht als Feld in einer anderen Klasse oder Struktur als einer ref-Struktur gespeichert werden.For example, it can't be stored as a field on a class or struct other than a ref struct. Um eine hohe Leistung zu erzielen, muss dieser Typ eine ref struct sein, da er die Eingabe ReadOnlySpan<byte>, die wiederum eine ref-Struktur ist, zwischenspeichern muss.To achieve high performance, this type must be a ref struct since it needs to cache the input ReadOnlySpan<byte>, which itself is a ref struct. Darüber hinaus ist dieser Typ änderbar, da er den Zustand enthält.In addition, this type is mutable since it holds state. Daher übergeben Sie ihn als Verweis anstatt als Wert.Therefore, pass it by ref rather than by value. Die Übergabe als Wert würde zu einer Strukturkopie führen, und die Zustandsänderungen wären für den Aufrufer nicht sichtbar.Passing it by value would result in a struct copy and the state changes would not be visible to the caller. Dies unterscheidet sich von Newtonsoft.Json, da der Newtonsoft.Json JsonTextReader eine Klasse ist.This differs from Newtonsoft.Json since the Newtonsoft.Json JsonTextReader is a class. Weitere Informationen zum Verwenden von ref-Strukturen finden Sie unter Schreiben von sicherem und effizientem C#-Code.For more information about how to use ref structs, see Write safe and efficient C# code.

Lesen von UTF-8-TextRead UTF-8 text

Um die bestmögliche Leistung bei Verwendung des Utf8JsonReader zu erzielen, lesen Sie JSON-Nutzlasten bereits als UTF-8-codierten Text und nicht als UTF-16-Zeichenfolgen.To achieve the best possible performance while using the Utf8JsonReader, read JSON payloads already encoded as UTF-8 text rather than as UTF-16 strings. Ein Codebeispiel finden Sie unter Filtern von Daten mithilfe von Utf8JsonReader.For a code example, see Filter data using Utf8JsonReader.

Lesen mit einem Stream oder PipeReaderRead with a Stream or PipeReader

Der Utf8JsonReader unterstützt das Lesen aus einem UTF-8-codierten ReadOnlySpan<byte> oder ReadOnlySequence<byte> (wobei es sich um das Ergebnis des Lesens aus einem PipeReader handelt).The Utf8JsonReader supports reading from a UTF-8 encoded ReadOnlySpan<byte> or ReadOnlySequence<byte> (which is the result of reading from a PipeReader).

Beim synchronen Lesen können Sie die JSON-Nutzlast bis zum Ende des Streams in ein Bytearray einlesen und dieses dann an den Reader übergeben.For synchronous reading, you could read the JSON payload until the end of the stream into a byte array and pass that into the reader. Zum Lesen aus einer Zeichenfolge (die UTF-16-codiert ist), rufen Sie UTF8.GetBytes auf,For reading from a string (which is encoded as UTF-16), call UTF8.GetBytes um die Zeichenfolge zuerst in ein UTF-8-codiertes Bytearray zu transcodieren.to first transcode the string to a UTF-8 encoded byte array. Übergeben Sie diese dann an den Utf8JsonReader.Then pass that to the Utf8JsonReader.

Da der Utf8JsonReader die Eingabe als JSON-Text betrachtet, wird eine UTF-8-Bytereihenfolgen-Marke (BOM) als ungültiges JSON-Format angesehen.Since the Utf8JsonReader considers the input to be JSON text, a UTF-8 byte order mark (BOM) is considered invalid JSON. Der Aufrufer muss dies ausfiltern, bevor die Daten an den Reader übergeben werden.The caller needs to filter that out before passing the data to the reader.

Codebeispiele finden Sie unter Verwenden von Utf8JsonReader.For code examples, see Use Utf8JsonReader.

Lesen mit „ReadOnlySequence“ mit mehreren SegmentenRead with multi-segment ReadOnlySequence

Wenn es sich bei Ihrer JSON-Eingabe um ein ReadOnlySpan<byte> handelt, kann auf jedes JSON-Element über die ValueSpan-Eigenschaft des Readers zugegriffen werden, während Sie die Leseschleife durchlaufen.If your JSON input is a ReadOnlySpan<byte>, each JSON element can be accessed from the ValueSpan property on the reader as you go through the read loop. Wenn Ihre Eingabe jedoch ein ReadOnlySequence<byte> ist (was das Ergebnis des Lesens aus einem PipeReader ist), können einige JSON-Elemente mehrere Segmente des ReadOnlySequence<byte>-Objekts umspannen.However, if your input is a ReadOnlySequence<byte> (which is the result of reading from a PipeReader), some JSON elements might straddle multiple segments of the ReadOnlySequence<byte> object. Auf diese Elemente könnte nicht über ValueSpan in einem zusammenhängenden Speicherblock zugegriffen werden.These elements would not be accessible from ValueSpan in a contiguous memory block. Rufen Sie stattdessen, immer wenn Sie ein aus mehreren Segmenten bestehendes ReadOnlySequence<byte> als Eingabe haben, die HasValueSequence-Eigenschaft des Readers ab, um zu ermitteln, wie der Zugriff auf das aktuelle JSON-Element erfolgen kann.Instead, whenever you have a multi-segment ReadOnlySequence<byte> as input, poll the HasValueSequence property on the reader to figure out how to access the current JSON element. Ein empfohlenes Muster finden Sie hier:Here's a recommended pattern:

while (reader.Read())
{
    switch (reader.TokenType)
    {
        // ...
        ReadOnlySpan<byte> jsonElement = reader.HasValueSequence ?
            reader.ValueSequence.ToArray() :
            reader.ValueSpan;
        // ...
    }
}

Verwenden von „ValueTextEquals“ für das Nachschlagen von EigenschaftsnamenUse ValueTextEquals for property name lookups

Verwenden Sie nicht ValueSpan, um byteweise Vergleiche durchzuführen, indem Sie SequenceEqual für das Nachschlagen von Eigenschaftennamen aufrufen.Don't use ValueSpan to do byte-by-byte comparisons by calling SequenceEqual for property name lookups. Rufen Sie stattdessen ValueTextEquals auf, da diese Methode die Escapezeichen von allen in JSON escapeten Zeichen entfernt.Call ValueTextEquals instead, because that method unescapes any characters that are escaped in the JSON. Hier finden Sie ein Beispiel, das zeigt, wie Sie nach einer Eigenschaft suchen, die „name“ heißt:Here's an example that shows how to search for a property that is named "name":

private static readonly byte[] s_nameUtf8 = Encoding.UTF8.GetBytes("name");
while (reader.Read())
{
    JsonTokenType tokenType = reader.TokenType;

    switch (tokenType)
    {
        case JsonTokenType.StartObject:
            total++;
            break;
        case JsonTokenType.PropertyName:
            if (reader.ValueTextEquals(s_nameUtf8))
            {
                count++;
            }
            break;
    }

Lesen von Nullwerten in Nullable-WerttypenRead null values into nullable value types

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.Newtonsoft.Json provides APIs that return Nullable<T>, such as ReadAsBoolean, which handles a Null TokenType for you by returning a bool?. Die integrierten System.Text.Json-APIs geben nur Non-Nullable-Werttypen zurück.The built-in System.Text.Json APIs return only non-nullable value types. Utf8JsonReader.GetBoolean gibt beispielsweise einen bool zurück.For example, Utf8JsonReader.GetBoolean returns a bool. Wenn es Null in JSON findet, löst es eine Ausnahme aus.It throws an exception if it finds Null in the JSON. In den folgenden Beispielen werden zwei Möglichkeiten zum Behandeln von Nullwerten veranschaulicht, eine, bei der ein Nullable-Werttyp zurückgegeben wird, und eine andere, bei der der Standardwert zurückgegeben wird:The following examples show two ways to handle nulls, one by returning a nullable value type and one by returning the default value:

public bool? ReadAsNullableBoolean()
{
    _reader.Read();
    if (_reader.TokenType == JsonTokenType.Null)
    {
        return null;
    }
    if (_reader.TokenType != JsonTokenType.True && _reader.TokenType != JsonTokenType.False)
    {
        throw new JsonException();
    }
    return _reader.GetBoolean();
}
public bool ReadAsBoolean(bool defaultValue)
{
    _reader.Read();
    if (_reader.TokenType == JsonTokenType.Null)
    {
        return defaultValue;
    }
    if (_reader.TokenType != JsonTokenType.True && _reader.TokenType != JsonTokenType.False)
    {
        throw new JsonException();
    }
    return _reader.GetBoolean();
}

Festlegung von ZielversionenMulti-targeting

Wenn Sie weiterhin Newtonsoft.Json für bestimmte Zielframeworks verwenden müssen, können Sie mehrere Zielversionen verwenden und zwei Implementierungen verwenden.If you need to continue to use Newtonsoft.Json for certain target frameworks, you can multi-target and have two implementations. Dies ist jedoch nicht trivial und erfordert einige #ifdefs sowie Quellduplizierung.However, this is not trivial and would require some #ifdefs and source duplication. Eine Möglichkeit, so viel Code wie möglich gemeinsam zu verwenden, besteht darin, Utf8JsonReader und Newtonsoft.Json JsonTextReader in einen ref struct-Wrapper einzuschließen.One way to share as much code as possible is to create a ref struct wrapper around Utf8JsonReader and Newtonsoft.Json JsonTextReader. Mit diesem Wrapper wird der öffentliche Oberflächenbereich vereinheitlicht, während die Verhaltensunterschiede isoliert werden.This wrapper would unify the public surface area while isolating the behavioral differences. 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.This lets you isolate the changes mainly to the construction of the type, along with passing the new type around by reference. Dies ist das Muster, an dem sich die Microsoft.Extensions.DependencyModel-Bibliothek orientiert:This is the pattern that the Microsoft.Extensions.DependencyModel library follows:

„Utf8JsonWriter“ im Vergleich zu „JsonTextWriter“Utf8JsonWriter compared to 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.System.Text.Json.Utf8JsonWriter is a high-performance way to write UTF-8 encoded JSON text from common .NET types like String, Int32, and DateTime. Der Writer ist ein Low-Level-Typ, der zum Erstellen von benutzerdefinierten Serialisierungsmodulen genutzt werden kann.The writer is a low-level type that can be used to build custom serializers.

In den folgenden Abschnitten werden empfohlene Programmiermuster für die Verwendung von Utf8JsonWriter erläutert.The following sections explain recommended programming patterns for using Utf8JsonWriter.

Schreiben mit UTF-8-TextWrite with UTF-8 text

Um die bestmögliche Leistung bei Verwendung des Utf8JsonWriter zu erzielen, schreiben Sie JSON-Nutzlasten bereits als UTF-8-codierten Text und nicht als UTF-16-Zeichenfolgen.To achieve the best possible performance while using the Utf8JsonWriter, write JSON payloads already encoded as UTF-8 text rather than as UTF-16 strings. Verwenden Sie JsonEncodedText, um bekannte Zeichenfolgen-Eigenschaftsnamen sowie -werte als statische Elemente zwischenzuspeichern und vorzucodieren, und übergeben Sie diese dann an den Writer, anstatt UTF-16-Zeichenfolgenliterale zu verwenden.Use JsonEncodedText to cache and pre-encode known string property names and values as statics, and pass those to the writer, rather than using UTF-16 string literals. Dies ist schneller als das Zwischenspeichern und Verwenden von UTF-8-Bytearrays.This is faster than caching and using UTF-8 byte arrays.

Diese Vorgehensweise funktioniert auch, wenn Sie benutzerdefiniert escapen müssen.This approach also works if you need to do custom escaping. System.Text.Json gestattet Ihnen nicht, während des Schreibens einer Zeichenfolge das Escapen zu deaktivieren.System.Text.Json doesn't let you disable escaping while writing a string. Sie können jedoch Ihren eigenen benutzerdefinierten JavaScriptEncoder als Option an den Writer übergeben oder Ihren eigenen JsonEncodedText erstellen, der Ihren JavascriptEncoder für das Escapen verwendet, und dann den JsonEncodedText anstelle der Zeichenfolge schreiben.However, you could pass in your own custom JavaScriptEncoder as an option to the writer, or create your own JsonEncodedText that uses your JavascriptEncoder to do the escaping, and then write the JsonEncodedText instead of the string. Weitere Informationen finden Sie unter Anpassen der Zeichencodierung.For more information, see Customize character encoding.

Schreiben von RohwertenWrite raw values

Die Newtonsoft.Json WriteRawValue-Methode schreibt JSON-Rohcode, wenn ein Wert erwartet wird.The Newtonsoft.Json WriteRawValue method writes raw JSON where a value is expected. System.Text.Json besitzt keine direkte Entsprechung, aber hier finden Sie eine Problemumgehung, die sicherstellt, dass nur gültiger JSON-Code geschrieben wird:System.Text.Json has no direct equivalent, but here's a workaround that ensures only valid JSON is written:

using JsonDocument doc = JsonDocument.Parse(string);
doc.WriteTo(writer);

Anpassen des Escapens von ZeichenCustomize character escaping

Die StringEscapeHandling--Einstellung von JsonTextWriter bietet Optionen, um alle Nicht-ASCII-Zeichen oder HTML-Zeichen zu escapen.The StringEscapeHandling setting of JsonTextWriter offers options to escape all non-ASCII characters or HTML characters. Standardmäßig escapet Utf8JsonWriter alle Nicht-ASCII- und HTML-Zeichen.By default, Utf8JsonWriter escapes all non-ASCII and HTML characters. Dieses Escapen erfolgt als tief greifende Abwehr aus Gründen des Schutzes.This escaping is done for defense-in-depth security reasons. Um eine andere Escaperichtlinie anzugeben, erstellen Sie einen JavaScriptEncoder, und legen Sie JsonWriterOptions.Encoder fest.To specify a different escaping policy, create a JavaScriptEncoder and set JsonWriterOptions.Encoder. Weitere Informationen finden Sie unter Anpassen der Zeichencodierung.For more information, see Customize character encoding.

Anpassen des JSON-FormatsCustomize JSON format

JsonTextWriter umfasst die folgenden Einstellungen, für die es bei Utf8JsonWriter keine Entsprechung gibt:JsonTextWriter includes the following settings, for which Utf8JsonWriter has no equivalent:

  • Indentation: Gibt an, um wie viele Zeichen ein Einzug erfolgen soll.Indentation - Specifies how many characters to indent. Utf8JsonWriter führt Einzüge immer um 2 Zeichen aus.Utf8JsonWriter always does 2-character indentation.
  • IndentChar: Gibt das für Einzüge zu verwendende Zeichen an.IndentChar - Specifies the character to use for indentation. Utf8JsonWriter verwendet immer Leerzeichen.Utf8JsonWriter always uses whitespace.
  • QuoteChar: Gibt das Zeichen an, das zum Umschließen von Zeichenfolgenwerten verwendet werden soll.QuoteChar - Specifies the character to use to surround string values. Utf8JsonWriter verwendet immer doppelte Anführungszeichen.Utf8JsonWriter always uses double quotes.
  • QuoteName: Gibt an, ob Eigenschaftsnamen in Anführungszeichen gesetzt werden sollen oder nicht.QuoteName - Specifies whether or not to surround property names with quotes. Utf8JsonWriter umschließt sie immer mit Anführungszeichen.Utf8JsonWriter always surrounds them with quotes.

Es gibt keine Problemumgehungen, mit denen Sie den von Utf8JsonWriter auf diese Weisen erzeugten JSON-Code anpassen können.There are no workarounds that would let you customize the JSON produced by Utf8JsonWriter in these ways.

Schreiben von NullwertenWrite null values

Um Nullwerte mithilfe von Utf8JsonWriter zu schreiben, rufen Sie Folgendes auf:To write null values by using Utf8JsonWriter, call:

  • WriteNull, um ein Schlüssel-Wert-Paar mit Null als Wert zu schreiben.WriteNull to write a key-value pair with null as the value.
  • WriteNullValue, um Null als Element eines JSON-Arrays zu schreiben.WriteNullValue to write null as an element of a JSON array.

Wenn eine Zeichenfolge Null ist, entsprechen bei einer Zeichenfolgeneigenschaft WriteString und WriteStringValue den Elementen WriteNull und WriteNullValue.For a string property, if the string is null, WriteString and WriteStringValue are equivalent to WriteNull and WriteNullValue.

Schreiben von TimeSpan-, Uri- oder char-WertenWrite Timespan, Uri, or char values

JsonTextWriter stellt WriteValue-Methoden für TimeSpan-, URI- und char-Werte bereit.JsonTextWriter provides WriteValue methods for TimeSpan, Uri, and char values. Utf8JsonWriter verfügt über keine entsprechenden Methoden.Utf8JsonWriter doesn't have equivalent methods. Formatieren Sie diese Werte stattdessen als Zeichenfolgen (z. B. durch Aufrufen von ToString()), und rufen Sie WriteStringValue auf.Instead, format these values as strings (by calling ToString(), for example) and call WriteStringValue.

Festlegung von ZielversionenMulti-targeting

Wenn Sie weiterhin Newtonsoft.Json für bestimmte Zielframeworks verwenden müssen, können Sie mehrere Zielversionen verwenden und zwei Implementierungen verwenden.If you need to continue to use Newtonsoft.Json for certain target frameworks, you can multi-target and have two implementations. Dies ist jedoch nicht trivial und erfordert einige #ifdefs sowie Quellduplizierung.However, this is not trivial and would require some #ifdefs and source duplication. Eine Möglichkeit, so viel Code wie möglich gemeinsam zu verwenden, besteht darin, Utf8JsonWriter und Newtonsoft JsonTextWriter in einen Wrapper einzuschließen.One way to share as much code as possible is to create a wrapper around Utf8JsonWriter and Newtonsoft JsonTextWriter. Mit diesem Wrapper wird der öffentliche Oberflächenbereich vereinheitlicht, während die Verhaltensunterschiede isoliert werden.This wrapper would unify the public surface area while isolating the behavioral differences. Auf diese Weise können Sie die Änderungen hauptsächlich auf die Konstruktion des Typs beschränken.This lets you isolate the changes mainly to the construction of the type. Die Microsoft.Extensions.DependencyModel-Bibliothek orientiert sich an:Microsoft.Extensions.DependencyModel library follows:

Zusätzliche RessourcenAdditional resources