Jak przeprowadzić migrację z Newtonsoft. JSON do System. Text. JSONHow to migrate from Newtonsoft.Json to System.Text.Json

W tym artykule pokazano, jak przeprowadzić migrację z Newtonsoft. JSON do System.Text.Json.This article shows how to migrate from Newtonsoft.Json to System.Text.Json.

System.Text.Json koncentruje się głównie na wydajności, zabezpieczeniach i zgodności ze standardami.System.Text.Json focuses primarily on performance, security, and standards compliance. Ma pewne kluczowe różnice w zachowaniu domyślnym i nie ma wpływu na funkcję z Newtonsoft.Json.It has some key differences in default behavior and doesn't aim to have feature parity with Newtonsoft.Json. W przypadku niektórych scenariuszy System.Text.Json nie ma wbudowanych funkcji, ale istnieją zalecane obejścia tego problemu.For some scenarios, System.Text.Json has no built-in functionality, but there are recommended workarounds. W przypadku innych scenariuszy obejścia są niepraktyczne.For other scenarios, workarounds are impractical. Jeśli aplikacja zależy od brakującej funkcji, rozważ zgłoszenie problemu , aby dowiedzieć się, czy można dodać wsparcie dla danego scenariusza.If your application depends on a missing feature, consider filing an issue to find out if support for your scenario can be added.

W większości tego artykułu zawarto informacje dotyczące korzystania z interfejsu API JsonSerializer, ale zawiera on również wskazówki dotyczące sposobu korzystania z JsonDocument (która reprezentuje typy Document Object Model lub DOM), Utf8JsonReaderi 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.

Tabela różnic między elementami Newtonsoft. JSON i system. Text. JSONTable of differences between Newtonsoft.Json and System.Text.Json

W poniższej tabeli wymieniono funkcje Newtonsoft.Json i System.Text.Json odpowiedniki.The following table lists Newtonsoft.Json features and System.Text.Json equivalents. Równoważne są następujące kategorie:The equivalents fall into the following categories:

  • Obsługiwane przez wbudowaną funkcję.Supported by built-in functionality. Uzyskanie podobnego zachowania z System.Text.Json może wymagać użycia atrybutu lub opcji globalnej.Getting similar behavior from System.Text.Json may require the use of an attribute or global option.
  • Nieobsługiwane, możliwe jest obejście tego problemu.Not supported, workaround is possible. Obejścia to niestandardowe konwertery, które mogą nie zapewniać pełnej parzystości z funkcjami Newtonsoft.Json.The workarounds are custom converters, which may not provide complete parity with Newtonsoft.Json functionality. W przypadku niektórych z nich przykładowy kod jest dostarczany jako przykłady.For some of these, sample code is provided as examples. Jeśli korzystasz z tych funkcji Newtonsoft.Json, migracja będzie wymagała modyfikacji modeli obiektów .NET lub innych zmian w kodzie.If you rely on these Newtonsoft.Json features, migration will require modifications to your .NET object models or other code changes.
  • Nieobsługiwane, obejście nie jest praktyczne ani możliwe.Not supported, workaround is not practical or possible. Jeśli korzystasz z tych funkcji Newtonsoft.Json, migracja nie będzie możliwa bez znaczących zmian.If you rely on these Newtonsoft.Json features, migration will not be possible without significant changes.
Newtonsoft. JSON — funkcjaNewtonsoft.Json feature Odpowiednik system. Text. JSONSystem.Text.Json equivalent
Deserializacja bez uwzględniania wielkości liter domyślnieCase-insensitive deserialization by default ✔️ Ustawienia globalne PropertyNameCaseInsensitive✔️ PropertyNameCaseInsensitive global setting
Notacji CamelCase — nazwy właściwości przypadkuCamel-case property names ✔️ Ustawienia globalne PropertyNamingPolicy✔️ PropertyNamingPolicy global setting
Znak ucieczki minimalnejMinimal character escaping ✔️ znaku ucieczki ścisłej, konfigurowalne✔️ Strict character escaping, configurable
NullValueHandling.Ignore ustawienie globalneNullValueHandling.Ignore global setting ✔️ IgnoreNullValues — opcja globalna✔️ IgnoreNullValues global option
Zezwalaj na KomentarzeAllow comments ✔️ Ustawienia globalne ReadCommentHandling✔️ ReadCommentHandling global setting
Zezwalaj na końcowe przecinkiAllow trailing commas ✔️ Ustawienia globalne AllowTrailingCommas✔️ AllowTrailingCommas global setting
Rejestracja niestandardowego konwerteraCustom converter registration ✔️ kolejność pierwszeństwa✔️ Order of precedence differs
Domyślnie nie ma głębokości maksymalnejNo maximum depth by default ✔️ Domyślna maksymalna głębokość 64, konfigurowalne✔️ Default maximum depth 64, configurable
Obsługa szerokiego zakresu typówSupport for a broad range of types ⚠️ niektóre typy wymagają konwerterów niestandardowych⚠️ Some types require custom converters
Deserializacja ciągów jako liczbyDeserialize strings as numbers Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
Deserializacja Dictionary przy użyciu klucza niebędącego ciągiemDeserialize Dictionary with non-string key Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
Serializacja polimorficznaPolymorphic serialization Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
Deserializacja polimorficznaPolymorphic deserialization Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
Zdeserializować typu wywnioskowanego do właściwości objectDeserialize inferred type to object properties Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
Deserializacja literału null JSON do typów niedopuszczających wartości nullDeserialize JSON null literal to non-nullable types Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
Deserializacja do niemodyfikowalnych klas i strukturDeserialize to immutable classes and structs Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
Atrybut [JsonConstructor][JsonConstructor] attribute Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
ustawienie Required w atrybucie [JsonProperty]Required setting on [JsonProperty] attribute Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
ustawienie NullValueHandling w atrybucie [JsonProperty]NullValueHandling setting on [JsonProperty] attribute Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
ustawienie DefaultValueHandling w atrybucie [JsonProperty]DefaultValueHandling setting on [JsonProperty] attribute Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
DefaultValueHandling ustawienie globalneDefaultValueHandling global setting Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
DefaultContractResolver do wykluczenia właściwościDefaultContractResolver to exclude properties Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
DateTimeZoneHandling, DateFormatString ustawieniaDateTimeZoneHandling, DateFormatString settings Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
Wywołania zwrotneCallbacks Nieobsługiwane ⚠️ , obejście, przykład⚠️ Not supported, workaround, sample
Obsługa pól publicznych i niepublicznychSupport for public and non-public fields Nieobsługiwane ⚠️ , obejście⚠️ Not supported, workaround
Obsługa wewnętrznych i prywatnych metod ustawiających właściwości i metod pobierającychSupport for internal and private property setters and getters Nieobsługiwane ⚠️ , obejście⚠️ Not supported, workaround
JsonConvert.PopulateObject, MetodaJsonConvert.PopulateObject method Nieobsługiwane ⚠️ , obejście⚠️ Not supported, workaround
ObjectCreationHandling ustawienie globalneObjectCreationHandling global setting Nieobsługiwane ⚠️ , obejście⚠️ Not supported, workaround
Dodaj do kolekcji bez metod ustawiającychAdd to collections without setters Nieobsługiwane ⚠️ , obejście⚠️ Not supported, workaround
PreserveReferencesHandling ustawienie globalnePreserveReferencesHandling global setting nieobsługiwaneNot supported
ReferenceLoopHandling ustawienie globalneReferenceLoopHandling global setting nieobsługiwaneNot supported
Obsługa atrybutów System.Runtime.SerializationSupport for System.Runtime.Serialization attributes nieobsługiwaneNot supported
MissingMemberHandling ustawienie globalneMissingMemberHandling global setting nieobsługiwaneNot supported
Zezwalaj na nazwy właściwości bez cudzysłowówAllow property names without quotes nieobsługiwaneNot supported
Zezwalaj na pojedyncze cudzysłowy wokół wartości ciąguAllow single quotes around string values nieobsługiwaneNot supported
Zezwalaj na wartości niebędące ciągami JSON dla właściwości ciąguAllow non-string JSON values for string properties nieobsługiwaneNot supported

Nie jest to pełna lista funkcji Newtonsoft.Json.This is not an exhaustive list of Newtonsoft.Json features. Lista zawiera wiele scenariuszy, które zostały zażądane w przypadku problemów z usługą GitHub lub wpisów StackOverflow .The list includes many of the scenarios that have been requested in GitHub issues or StackOverflow posts. Jeśli zaimplementowano obejście dla jednego z wymienionych poniżej scenariuszy, które nie ma obecnie przykładowego kodu, a jeśli chcesz udostępnić swoje rozwiązanie, wybierz Tę stronę w sekcji opinia na tej stronie.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 of this page. Spowoduje to utworzenie problemu w usłudze GitHub i wyświetlenie go w dolnej części tej strony.That creates a GitHub issue and lists it at the bottom of this page.

Różnice dotyczące domyślnego zachowania JsonSerializer w porównaniu do Newtonsoft. JSONDifferences in default JsonSerializer behavior compared to Newtonsoft.Json

System.Text.Json jest domyślnie rygorystyczne i pozwala uniknąć wszelkich odgadnąć lub interpretacji w imieniu wywołującego, podkreślając deterministyczne zachowanie.System.Text.Json is strict by default and avoids any guessing or interpretation on the caller's behalf, emphasizing deterministic behavior. Biblioteka jest celowo zaprojektowana w taki sposób, aby uzyskać wydajność i bezpieczeństwo.The library is intentionally designed this way for performance and security. Domyślnie Newtonsoft.Json jest elastyczny.Newtonsoft.Json is flexible by default. Ta podstawowa różnica w projekcie jest zbyt wiele z poniższych konkretnych różnic w domyślnym zachowaniu.This fundamental difference in design is behind many of the following specific differences in default behavior.

Deserializacja bez uwzględniania wielkości literCase-insensitive deserialization

Podczas deserializacji Newtonsoft.Json domyślnie dopasowywania nazw właściwości bez uwzględniania wielkości liter.During deserialization, Newtonsoft.Json does case-insensitive property name matching by default. W System.Text.Json domyślnym rozróżniana jest wielkość liter, co zapewnia lepszą wydajność, ponieważ jest to dokładne dopasowanie.The System.Text.Json default is case-sensitive, which gives better performance since it's doing an exact match. Aby uzyskać informacje o sposobie dopasowywania wielkości liter, zobacz dopasowanie do wielkościliter.For information about how to do case-insensitive matching, see Case-insensitive property matching.

Jeśli używasz System.Text.Json pośrednio przy użyciu ASP.NET Core, nie musisz nic robić, aby uzyskać zachowanie takie jak Newtonsoft.Json.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 określa ustawienia nazw właściwości notacji CamelCase i bez uwzględniania wielkości liter, gdy używa System.Text.Json.ASP.NET Core specifies the settings for camel-casing property names and case-insensitive matching when it uses System.Text.Json.

Znak ucieczki minimalnejMinimal character escaping

Podczas serializacji Newtonsoft.Json jest relatywnie ograniczając, aby zezwalać na znaki, bez ucieczki.During serialization, Newtonsoft.Json is relatively permissive about letting characters through without escaping them. Oznacza to, że nie zastępuje ich \uxxxx, gdzie xxxx jest punktem kodu znaku.That is, it doesn't replace them with \uxxxx where xxxx is the character's code point. Tam, gdzie wykonuje te zmiany, robi to, emitując \ przed znakiem (na przykład " zostanie \").Where it does escape them, it does so by emitting a \ before the character (for example, " becomes \"). System.Text.Json domyślnie uzupełnia więcej znaków, aby zapewnić ochronę przed ochroną przed wieloma lokacjami (XSS) lub ataki z ujawnianiem informacji, a tym samym przy użyciu sekwencji składającej się z sześciu znaków.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 domyślnie wyprowadza wszystkie znaki inne niż ASCII, więc nie trzeba wykonywać żadnych czynności, jeśli używasz StringEscapeHandling.EscapeNonAscii w Newtonsoft.Json.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 również domyślnie wyprowadza znaki z uwzględnieniem kodu HTML.System.Text.Json also escapes HTML-sensitive characters, by default. Aby dowiedzieć się, jak zastąpić domyślne zachowanie System.Text.Json, zobacz Dostosowywanie kodowania znaków.For information about how to override the default System.Text.Json behavior, see Customize character encoding.

KomentarzeComments

Podczas deserializacji Newtonsoft.Json domyślnie ignoruje komentarze w formacie JSON.During deserialization, Newtonsoft.Json ignores comments in the JSON by default. Domyślnie System.Text.Json ma zgłosić wyjątki dla komentarzy, ponieważ Specyfikacja RFC 8259 nie zawiera ich.The System.Text.Json default is to throw exceptions for comments because the RFC 8259 specification doesn't include them. Aby uzyskać informacje o sposobach zezwalania na komentarze, zobacz Zezwalanie na komentarze i końcowe przecinki.For information about how to allow comments, see Allow comments and trailing commas.

Końcowe przecinkiTrailing commas

Podczas deserializacji Newtonsoft.Json domyślnie ignoruje końcowe przecinki.During deserialization, Newtonsoft.Json ignores trailing commas by default. Ignoruje także kilka końcowych przecinków (na przykład [{"Color":"Red"},{"Color":"Green"},,]).It also ignores multiple trailing commas (for example, [{"Color":"Red"},{"Color":"Green"},,]). Domyślnie System.Text.Json ma zgłosić wyjątki dla końcowych przecinków, ponieważ Specyfikacja RFC 8259 nie zezwala.The System.Text.Json default is to throw exceptions for trailing commas because the RFC 8259 specification doesn't allow them. Aby uzyskać informacje na temat sposobu ich akceptowania System.Text.Json, zobacz Zezwalanie na komentarze i końcowe przecinki.For information about how to make System.Text.Json accept them, see Allow comments and trailing commas. Nie ma możliwości zezwalania na wielokrotne końcowe przecinki.There's no way to allow multiple trailing commas.

Pierwszeństwo rejestracji konwerteraConverter registration precedence

Priorytet rejestracji Newtonsoft.Json dla konwerterów niestandardowych jest następujący:The Newtonsoft.Json registration precedence for custom converters is as follows:

  • Atrybut właściwościAttribute on property
  • Atrybut typuAttribute on type
  • Kolekcja konwerterówConverters collection

Ta kolejność oznacza, że konwerter niestandardowy w kolekcji Converters jest zastępowany przez konwerter zarejestrowany przez zastosowanie atrybutu na poziomie typu.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. Obie te rejestracje są zastępowane przez atrybut na poziomie właściwości.Both of those registrations are overridden by an attribute at the property level.

Pierwszeństwo rejestracji System.Text.Json dla konwerterów niestandardowych jest inne:The System.Text.Json registration precedence for custom converters is different:

  • Atrybut właściwościAttribute on property
  • Kolekcja ConvertersConverters collection
  • Atrybut typuAttribute on type

Różnica polega na tym, że konwerter niestandardowy w kolekcji Converters przesłania atrybut na poziomie typu.The difference here is that a custom converter in the Converters collection overrides an attribute at the type level. Zamierzone jest zamierzenie, aby zmiany w czasie wykonywania zastępowały opcje czasu projektowania.The intention behind this order of precedence is to make run-time changes override design-time choices. Nie ma możliwości zmiany pierwszeństwa.There's no way to change the precedence.

Aby uzyskać więcej informacji na temat rejestrowania niestandardowego konwertera, zobacz Rejestrowanie niestandardowego konwertera.For more information about custom converter registration, see Register a custom converter.

Maksymalna głębokośćMaximum depth

Newtonsoft.Json domyślnie nie ma maksymalnego limitu głębokości.Newtonsoft.Json doesn't have a maximum depth limit by default. W przypadku System.Text.Json istnieje domyślny limit 64 i można go skonfigurować przez ustawienie JsonSerializerOptions.MaxDepth.For System.Text.Json there's a default limit of 64, and it's configurable by setting JsonSerializerOptions.MaxDepth.

Ciągi JSON (nazwy właściwości i wartości ciągów)JSON strings (property names and string values)

Podczas deserializacji Newtonsoft.Json akceptuje nazwy właściwości ujęte w podwójne cudzysłowy, apostrofy lub bez cudzysłowu.During deserialization, Newtonsoft.Json accepts property names surrounded by double quotes, single quotes, or without quotes. Akceptuje wartości ciągów ujęte w cudzysłów lub pojedyncze cudzysłowy.It accepts string values surrounded by double quotes or single quotes. Na przykład Newtonsoft.Json akceptuje następujący kod JSON:For example, Newtonsoft.Json accepts the following JSON:

{
  "name1": "value",
  'name2': "value",
  name3: 'value'
}

System.Text.Json akceptuje tylko nazwy właściwości i wartości ciągu w podwójnych cudzysłowach, ponieważ ten format jest wymagany przez specyfikację RFC 8259 i jest jedynym formatem uważanym za prawidłowy kod JSON.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.

Wartość zawarta w pojedynczym cudzysłowie powoduje, że element jsonexception z następującym komunikatem:A value enclosed in single quotes results in a JsonException with the following message:

''' is an invalid start of a value.

Wartości niebędące ciągami dla właściwości ciąguNon-string values for string properties

Newtonsoft.Json akceptuje wartości niebędące ciągami, takie jak liczba lub literały true i false, dla deserializacji do właściwości typu String.Newtonsoft.Json accepts non-string values, such as a number or the literals true and false, for deserialization to properties of type string. Oto przykład kodu JSON, który Newtonsoft.Json pomyślnie deserializacji do następującej klasy: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 nie deserializacji wartości niebędących ciągami na właściwości ciągu.System.Text.Json doesn't deserialize non-string values into string properties. Odebrana wartość niebędąca ciągiem dla pola ciągu powoduje wyrażenie jsonexception z następującym komunikatem: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.

Scenariusze korzystające z JsonSerializer, które wymagają obejściaScenarios using JsonSerializer that require workarounds

Następujące scenariusze nie są obsługiwane przez funkcje wbudowane, ale możliwe jest obejście tego problemu.The following scenarios aren't supported by built-in functionality, but workarounds are possible. Obejścia to niestandardowe konwertery, które mogą nie zapewniać pełnej parzystości z funkcjami Newtonsoft.Json.The workarounds are custom converters, which may not provide complete parity with Newtonsoft.Json functionality. W przypadku niektórych z nich przykładowy kod jest dostarczany jako przykłady.For some of these, sample code is provided as examples. Jeśli korzystasz z tych funkcji Newtonsoft.Json, migracja będzie wymagała modyfikacji modeli obiektów .NET lub innych zmian w kodzie.If you rely on these Newtonsoft.Json features, migration will require modifications to your .NET object models or other code changes.

Typy bez wbudowanej obsługiTypes without built-in support

System.Text.Json nie zapewnia wbudowanego wsparcia dla następujących typów:System.Text.Json doesn't provide built-in support for the following types:

Konwertery niestandardowe można zaimplementować dla typów, które nie mają wbudowanej obsługi.Custom converters can be implemented for types that don't have built-in support.

Liczby ujęte w cudzysłówQuoted numbers

Newtonsoft.Json może serializować lub deserializować liczby reprezentowane przez ciągi JSON (ujęte w cudzysłowy).Newtonsoft.Json can serialize or deserialize numbers represented by JSON strings (surrounded by quotes). Na przykład może akceptować: {"DegreesCelsius":"23"}, a nie {"DegreesCelsius":23}.For example, it can accept: {"DegreesCelsius":"23"} instead of {"DegreesCelsius":23}. Aby włączyć to zachowanie w System.Text.Json, zaimplementuj niestandardowy konwerter, jak w poniższym przykładzie.To enable that behavior in System.Text.Json, implement a custom converter like the following example. Konwerter obsługuje właściwości zdefiniowane jako long:The converter handles properties defined as long:

  • Serializować je jako ciągi JSON.It serializes them as JSON strings.
  • Akceptuje liczby i cyfry JSON w cudzysłowie podczas deserializacji.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());
        }
    }
}

Zarejestrowanie tego konwertera niestandardowego przy użyciu atrybutu dla poszczególnych właściwości long lub poprzez dodanie konwertera do kolekcji Converters.Register this custom converter by using an attribute on individual long properties or by adding the converter to the Converters collection.

Słownik z kluczem niebędącym ciągiemDictionary with non-string key

Newtonsoft.Json obsługuje kolekcje typu Dictionary<TKey, TValue>.Newtonsoft.Json supports collections of type Dictionary<TKey, TValue>. Wbudowana obsługa kolekcji słowników w System.Text.Json jest ograniczona do Dictionary<string, TValue>.The built-in support for dictionary collections in System.Text.Json is limited to Dictionary<string, TValue>. Oznacza to, że klucz musi być ciągiem.That is, the key must be a string.

Aby zapewnić obsługę słownika z liczbą całkowitą lub innym typem jako klucz, Utwórz konwerter jak przykład w temacie How to Write Custom Converters.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.

Serializacja polimorficznaPolymorphic serialization

Newtonsoft.Json automatycznie wykonuje serializacji polimorficznej.Newtonsoft.Json automatically does polymorphic serialization. Aby uzyskać informacje o ograniczonych możliwościach serializacji polimorficznej System.Text.Json, zobacz Serializowanie właściwości klas pochodnych.For information about the limited polymorphic serialization capabilities of System.Text.Json, see Serialize properties of derived classes.

Opisane obejście ma na celu zdefiniowanie właściwości, które mogą zawierać klasy pochodne jako typ object.The workaround described there is to define properties that may contain derived classes as type object. Jeśli to nie jest możliwe, kolejną opcją jest utworzenie konwertera z metodą Write dla całej hierarchii typów dziedziczenia, na przykład w przypadku pisania konwerterów niestandardowych.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.

Deserializacja polimorficznaPolymorphic deserialization

Newtonsoft.Json ma ustawienie TypeNameHandling, które dodaje metadane nazwy typu do JSON podczas serializacji.Newtonsoft.Json has a TypeNameHandling setting that adds type name metadata to the JSON while serializing. Używa metadanych podczas deserializacji w celu wykonania deserializacji polimorficznej.It uses the metadata while deserializing to do polymorphic deserialization. System.Text.Json może wykonywać ograniczony zakres serializacji polimorficznej , ale nie deserializacji polimorficznej.System.Text.Json can do a limited range of polymorphic serialization but not polymorphic deserialization.

Aby obsłużyć deserializacja polimorficzna, Utwórz konwerter, taki jak przykład, w jaki sposób pisać konwertery niestandardowe.To support polymorphic deserialization, create a converter like the example in How to write custom converters.

Deserializacja właściwości obiektuDeserialization of object properties

Gdy Newtonsoft.Json deserializacji do Object, to:When Newtonsoft.Json deserializes to Object, it:

  • Wnioskuje typ wartości pierwotnych w ładunku JSON (innym niż null) i zwraca przechowywane string, long, double, booleanlub DateTime jako obiekt opakowany.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. Wartości pierwotne to pojedyncze wartości JSON, takie jak numer JSON, ciąg, true, falselub null.Primitive values are single JSON values such as a JSON number, string, true, false, or null.
  • Zwraca JObject lub JArray dla wartości złożonych w ładunku JSON.Returns a JObject or JArray for complex values in the JSON payload. Wartości złożone to kolekcje par klucz-wartość JSON w nawiasach klamrowych ({}) lub listy wartości w nawiasach kwadratowych ([]).Complex values are collections of JSON key-value pairs within braces ({}) or lists of values within brackets ([]). Właściwości i wartości w nawiasach klamrowych mogą mieć dodatkowe właściwości lub wartości.The properties and values within the braces or brackets can have additional properties or values.
  • Zwraca odwołanie o wartości null, gdy ładunek ma nully literał JSON.Returns a null reference when the payload has the null JSON literal.

System.Text.Json przechowuje JsonElement opakowane dla wartości pierwotnych i złożonych przy każdej deserializacji do Object, na przykład:System.Text.Json stores a boxed JsonElement for both primitive and complex values whenever deserializing to Object, for example:

  • Właściwość object.An object property.
  • Wartość słownika object.An object dictionary value.
  • Wartość tablicy object.An object array value.
  • objectgłówny.A root object.

Jednakże System.Text.Json traktuje null tak samo jak Newtonsoft.Json i zwraca odwołanie o wartości null, gdy ładunek zawiera null w nim literał JSON.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.

Aby zaimplementować wnioskowanie o właściwościach object, Utwórz konwerter jak przykład w temacie How to Write Custom Converters.To implement type inference for object properties, create a converter like the example in How to write custom converters.

Deserializacja wartości null na typ niedopuszczający wartości nullDeserialize null to non-nullable type

Newtonsoft.Json nie zgłasza wyjątku w następującym scenariuszu:Newtonsoft.Json doesn't throw an exception in the following scenario:

  • NullValueHandling jest ustawiony na IgnoreiNullValueHandling is set to Ignore, and
  • Podczas deserializacji kod JSON zawiera wartość null dla typu, który nie dopuszcza wartości null.During deserialization, the JSON contains a null value for a non-nullable type.

W tym samym scenariuszu System.Text.Json generuje wyjątek.In the same scenario, System.Text.Json does throw an exception. (Odpowiednie ustawienie obsługi wartości null to JsonSerializerOptions.IgnoreNullValues.)(The corresponding null handling setting is JsonSerializerOptions.IgnoreNullValues.)

Jeśli jesteś własnym typem docelowym, najlepszym obejściem jest to, że właściwość w pytaniu nie dopuszcza wartości null (na przykład zmiana int na int?).If you own the target type, the best workaround is to make the property in question nullable (for example, change int to int?).

Innym obejściem jest tworzenie konwertera dla typu, takiego jak Poniższy przykład, który obsługuje wartości null dla typów DateTimeOffset: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);
        }
    }
}

Zarejestrowanie tego konwertera niestandardowego przy użyciu atrybutu właściwości lub przez dodanie konwertera do kolekcji Converters.Register this custom converter by using an attribute on the property or by adding the converter to the Converters collection.

Uwaga: Poprzedni konwerter obsługuje wartości null inaczej niż Newtonsoft.Json dla POCOs, które określają wartości domyślne.Note: The preceding converter handles null values differently than Newtonsoft.Json does for POCOs that specify default values. Załóżmy na przykład, że następujący kod reprezentuje obiekt docelowy: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; }
}

Załóżmy, że następujący kod JSON jest deserializowany przy użyciu poprzedniego konwertera:And suppose the following JSON is deserialized by using the preceding converter:

{
  "Date": null,
  "TemperatureCelsius": 25,
  "Summary": null
}

Po deserializacji właściwość Date ma 1/1/0001 (default(DateTimeOffset)), oznacza to, że wartość ustawiona w konstruktorze jest zastępowana.After deserialization, the Date property has 1/1/0001 (default(DateTimeOffset)), that is, the value set in the constructor is overwritten. Mając te same POCO i kod JSON, Newtonsoft.Json deserializacji spowodowałaby pozostawienie 1/1/2001 we właściwości Date.Given the same POCO and JSON, Newtonsoft.Json deserialization would leave 1/1/2001 in the Date property.

Deserializacja do niemodyfikowalnych klas i strukturDeserialize to immutable classes and structs

Newtonsoft.Json może deserializować do niemodyfikowalnych klas i struktur, ponieważ może używać konstruktorów z parametrami.Newtonsoft.Json can deserialize to immutable classes and structs because it can use constructors that have parameters. System.Text.Json obsługuje tylko publiczne konstruktory bez parametrów.System.Text.Json supports only public parameterless constructors. Jako obejście można wywołać konstruktora z parametrami w niestandardowym konwerterze.As a workaround, you can call a constructor with parameters in a custom converter.

Oto niezmienna struktura z wieloma parametrami konstruktora: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; }
}

A oto konwerter, który serializować i deserializacji tej struktury: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();
        }
    }
}

Zarejestruj ten konwerter niestandardowy, dodając konwerter do kolekcji Converters.Register this custom converter by adding the converter to the Converters collection.

Aby zapoznać się z przykładem podobnego konwertera, który obsługuje otwarte właściwości ogólne, zobacz wbudowany konwerter par klucz-wartość.For an example of a similar converter that handles open generic properties, see the built-in converter for key-value pairs.

Określ Konstruktor do użyciaSpecify constructor to use

Atrybut [JsonConstructor] Newtonsoft.Json pozwala określić Konstruktor, który ma być wywoływany podczas deserializacji do POCO.The Newtonsoft.Json [JsonConstructor] attribute lets you specify which constructor to call when deserializing to a POCO. System.Text.Json obsługuje tylko konstruktory bez parametrów.System.Text.Json supports only parameterless constructors. Jako obejście można wywołać każdy Konstruktor, którego potrzebujesz w niestandardowym konwerterze.As a workaround, you can call whichever constructor you need in a custom converter. Zobacz przykład dla deserializacji do niemodyfikowalnych klas i struktur.See the example for Deserialize to immutable classes and structs.

Wymagane właściwościRequired properties

W Newtonsoft.Jsonnależy określić, że właściwość jest wymagana przez ustawienie Required atrybutu [JsonProperty].In Newtonsoft.Json, you specify that a property is required by setting Required on the [JsonProperty] attribute. Newtonsoft.Json zgłasza wyjątek, jeśli żadna wartość nie zostanie odebrana w formacie JSON dla właściwości oznaczonej jako wymagane.Newtonsoft.Json throws an exception if no value is received in the JSON for a property marked as required.

System.Text.Json nie zgłasza wyjątku, jeśli nie otrzymano żadnej wartości dla jednej z właściwości typu docelowego.System.Text.Json doesn't throw an exception if no value is received for one of the properties of the target type. Na przykład jeśli masz klasę WeatherForecast: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; }
}

Następujący kod JSON jest deserializowany bez błędu:The following JSON is deserialized without error:

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

Aby deserializacja nie powiodła się, jeśli w kodzie JSON nie ma właściwości Date, zaimplementuj konwerter niestandardowy.To make deserialization fail if no Date property is in the JSON, implement a custom converter. Następujący przykładowy kod konwertera zgłasza wyjątek, jeśli właściwość Date nie jest ustawiona po zakończeniu deserializacji: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);
        }
    }
}

Zarejestrowanie tego konwertera niestandardowego przy użyciu atrybutu klasy poco lub poprzez dodanie konwertera do kolekcji Converters.Register this custom converter by using an attribute on the POCO class or by adding the converter to the Converters collection.

W przypadku przestrzegania tego wzorca nie należy przechodzić do obiektu options podczas rekursywnego wywoływania Serialize lub Deserialize.If you follow this pattern, don't pass in the options object when recursively calling Serialize or Deserialize. Obiekt Options zawiera kolekcję Converters.The options object contains the Converters collection. Jeśli przekażesz go do Serialize lub Deserialize, konwerter niestandardowy wywołuje się do siebie, tworząc nieskończoną pętlę, która powoduje wyjątek przepełnienia stosu.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. Jeśli opcje domyślne nie są możliwe, Utwórz nowe wystąpienie opcji z ustawieniami, które są potrzebne.If the default options are not feasible, create a new instance of the options with the settings that you need. Takie podejście będzie powolne, ponieważ każde nowe wystąpienie pamięci podręcznej jest niezależne.This approach will be slow since each new instance caches independently.

Poprzedni kod konwertera to uproszczony przykład.The preceding converter code is a simplified example. Dodatkowa logika powinna być wymagana, jeśli trzeba obsługiwać atrybuty (takie jak [JsonIgnore] lub różne opcje (takie jak kodery niestandardowe).Additional logic would be required if you need to handle attributes (such as [JsonIgnore] or different options (such as custom encoders). Ponadto przykładowy kod nie obsługuje właściwości, dla których ustawiono wartość domyślną w konstruktorze.Also, the example code doesn't handle properties for which a default value is set in the constructor. To podejście nie różni się między następującymi scenariuszami:And this approach doesn't differentiate between the following scenarios:

  • Brak właściwości w kodzie JSON.A property is missing from the JSON.
  • Właściwość typu niedopuszczający wartości null jest obecna w notacji JSON, ale wartość jest wartością domyślną dla tego typu, np. zero dla 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.
  • Właściwość dla typu dopuszczającego wartość null jest obecna w notacji JSON, ale wartość jest równa null.A property for a nullable type is present in the JSON, but the value is null.

Warunkowo Ignoruj WłaściwośćConditionally ignore a property

Newtonsoft.Json ma kilka sposobów, aby warunkowo ignorować właściwość podczas serializacji lub deserializacji:Newtonsoft.Json has several ways to conditionally ignore a property on serialization or deserialization:

  • DefaultContractResolver umożliwia wybranie właściwości, które mają zostać dołączone lub wykluczone w oparciu o dowolne kryteria.DefaultContractResolver lets you select properties to include or exclude, based on arbitrary criteria.
  • Ustawienia NullValueHandling i DefaultValueHandling na JsonSerializerSettings pozwalają określić, że wszystkie właściwości null-value lub wartość domyślna wartości powinny być ignorowane.The NullValueHandling and DefaultValueHandling settings on JsonSerializerSettings let you specify that all null-value or default-value properties should be ignored.
  • Ustawienia NullValueHandling i DefaultValueHandling w atrybucie [JsonProperty] umożliwiają określanie poszczególnych właściwości, które mają być ignorowane, gdy wartość jest równa null lub wartości domyślnej.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 oferuje następujące sposoby pomijania właściwości podczas serializacji:System.Text.Json provides the following ways to omit properties while serializing:

  • Atrybut [JsonIgnore] właściwości powoduje pominięcie właściwości z poziomu JSON podczas serializacji.The [JsonIgnore] attribute on a property causes the property to be omitted from the JSON during serialization.
  • Opcja globalna IgnoreNullValues umożliwia wykluczenie wszystkich właściwości o wartości null.The IgnoreNullValues global option lets you exclude all null-value properties.
  • Opcja globalna IgnoreReadOnlyProperties umożliwia wykluczenie wszystkich właściwości tylko do odczytu.The IgnoreReadOnlyProperties global option lets you exclude all read-only properties.

Te opcje nie pozwalają:These options don't let you:

  • Zignoruj wszystkie właściwości, które mają wartość domyślną dla tego typu.Ignore all properties that have the default value for the type.
  • Ignoruj wybrane właściwości, które mają wartość domyślną dla tego typu.Ignore selected properties that have the default value for the type.
  • Ignoruj wybrane właściwości, jeśli ich wartość jest równa null.Ignore selected properties if their value is null.
  • Ignoruj wybrane właściwości na podstawie arbitralnych kryteriów ocenionych w czasie wykonywania.Ignore selected properties based on arbitrary criteria evaluated at run time.

W przypadku tej funkcji można napisać konwerter niestandardowy.For that functionality, you can write a custom converter. Oto przykład POCO i niestandardowy konwerter dla niego, który ilustruje następujące podejście: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();
        }
    }
}

Konwerter powoduje pominięcie właściwości Summary z serializacji, jeśli jej wartość jest równa null, pusty ciąg lub "N/A".The converter causes the Summary property to be omitted from serialization if its value is null, an empty string, or "N/A".

Zarejestrowanie tego konwertera niestandardowego przy użyciu atrybutu klasy lub przez dodanie konwertera do kolekcji Converters.Register this custom converter by using an attribute on the class or by adding the converter to the Converters collection.

Takie podejście wymaga dodatkowej logiki, jeśli:This approach requires additional logic if:

  • POCO zawiera złożone właściwości.The POCO includes complex properties.
  • Musisz obsługiwać atrybuty, takie jak [JsonIgnore] lub opcje, takie jak kodery niestandardowe.You need to handle attributes such as [JsonIgnore] or options such as custom encoders.

Określ format datySpecify date format

Newtonsoft.Json oferuje kilka sposobów, aby kontrolować sposób serializacji i deserializacji właściwości typów DateTime i DateTimeOffset:Newtonsoft.Json provides several ways to control how properties of DateTime and DateTimeOffset types are serialized and deserialized:

  • Ustawienie DateTimeZoneHandling może służyć do serializacji wszystkich wartości DateTime jako daty UTC.The DateTimeZoneHandling setting can be used to serialize all DateTime values as UTC dates.
  • Ustawienia DateFormatString i konwerterów DateTime mogą służyć do dostosowywania formatu ciągów daty.The DateFormatString setting and DateTime converters can be used to customize the format of date strings.

W System.Text.Jsonjedynym formatem, który ma wbudowaną obsługę, jest ISO 8601-1:2019, ponieważ jest on powszechnie przyjęty, niejednoznaczny i umożliwia precyzyjne przekazanie rundy.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. Aby użyć innego formatu, Utwórz konwerter niestandardowy.To use any other format, create a custom converter. Aby uzyskać więcej informacji, zobacz Obsługa DateTime i DateTimeOffset w pliku System. Text. JSON.For more information, see DateTime and DateTimeOffset support in System.Text.Json.

Wywołania zwrotneCallbacks

Newtonsoft.Json umożliwia wykonywanie kodu niestandardowego w kilku punktach w procesie serializacji lub deserializacji:Newtonsoft.Json lets you execute custom code at several points in the serialization or deserialization process:

  • OnDeserializing (przy rozpoczynaniu deserializacji obiektu)OnDeserializing (when beginning to deserialize an object)
  • Onserializacja (po zakończeniu deserializacji obiektu)OnDeserialized (when finished deserializing an object)
  • Onserializacja (gdy zaczynasz serializować obiekt)OnSerializing (when beginning to serialize an object)
  • Onserialed (po zakończeniu serializacji obiektu)OnSerialized (when finished serializing an object)

W System.Text.Jsonmożna symulować wywołania zwrotne, pisząc konwertery niestandardowe.In System.Text.Json, you can simulate callbacks by writing a custom converter. W poniższym przykładzie przedstawiono niestandardowy konwerter dla POCO.The following example shows a custom converter for a POCO. Konwerter zawiera kod, który wyświetla komunikat w każdym punkcie, który odpowiada Newtonsoft.Json wywołanie zwrotne.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");
        }
    }
}

Zarejestrowanie tego konwertera niestandardowego przy użyciu atrybutu klasy lub przez dodanie konwertera do kolekcji <xref:[!OP.NO-LOC(System.Text.Json)].JsonSerializerOptions.Converters>.Register this custom converter by using an attribute on the class or by adding the converter to the Converters collection.

Jeśli używasz niestandardowego konwertera, który następuje po powyższym przykładzie:If you use a custom converter that follows the preceding sample:

  • Kod OnDeserializing nie ma dostępu do nowego wystąpienia POCO.The OnDeserializing code doesn't have access to the new POCO instance. Aby manipulować nowym wystąpieniem POCO na początku deserializacji, Umieść ten kod w konstruktorze POCO.To manipulate the new POCO instance at the start of deserialization, put that code in the POCO constructor.
  • Nie przekazuj w obiekcie Options podczas rekursywnego wywoływania Serialize lub Deserialize.Don't pass in the options object when recursively calling Serialize or Deserialize. Obiekt Options zawiera kolekcję Converters.The options object contains the Converters collection. Jeśli przekażesz go do Serialize lub Deserialize, zostanie użyty konwerter, dzięki czemu nieskończona pętla powoduje wyjątek przepełnienia stosu.If you pass it in to Serialize or Deserialize, the converter will be used, making an infinite loop that results in a stack overflow exception.

Pola publiczne i niepublicznePublic and non-public fields

Newtonsoft.Json może serializować i deserializować pola oraz właściwości.Newtonsoft.Json can serialize and deserialize fields as well as properties. System.Text.Json działa tylko z właściwościami publicznymi.System.Text.Json only works with public properties. Te funkcje mogą zapewniać konwertery niestandardowe.Custom converters can provide this functionality.

Metody i metody pobierające właściwości wewnętrznych i prywatnychInternal and private property setters and getters

Newtonsoft.Json może używać prywatnych i wewnętrznych metod ustawiających właściwości i metody pobierającej za pośrednictwem atrybutu JsonProperty.Newtonsoft.Json can use private and internal property setters and getters via the JsonProperty attribute. System.Text.Json obsługuje tylko publiczne metody ustawiające.System.Text.Json supports only public setters. Te funkcje mogą zapewniać konwertery niestandardowe.Custom converters can provide this functionality.

Wypełnij istniejące obiektyPopulate existing objects

Metoda JsonConvert.PopulateObject w Newtonsoft.Json deserializacji dokumentu JSON do istniejącego wystąpienia klasy, zamiast tworzyć nowe wystąpienie.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 zawsze tworzy nowe wystąpienie typu docelowego przy użyciu domyślnego publicznego konstruktora bez parametrów.System.Text.Json always creates a new instance of the target type by using the default public parameterless constructor. Konwertery niestandardowe mogą zdeserializować do istniejącego wystąpienia.Custom converters can deserialize to an existing instance.

Użyj ponownie zamiast właściwości ZamieńReuse rather than replace properties

Ustawienie ObjectCreationHandling Newtonsoft.Json pozwala określić, że obiekty w właściwości powinny być ponownie używane, a nie zastąpione podczas deserializacji.The Newtonsoft.Json ObjectCreationHandling setting lets you specify that objects in properties should be reused rather than replaced during deserialization. System.Text.Json zawsze zastępuje obiekty we właściwościach.System.Text.Json always replaces objects in properties. Te funkcje mogą zapewniać konwertery niestandardowe.Custom converters can provide this functionality.

Dodaj do kolekcji bez metod ustawiającychAdd to collections without setters

Podczas deserializacji Newtonsoft.Json dodaje obiekty do kolekcji, nawet jeśli właściwość nie ma metody ustawiającej.During deserialization, Newtonsoft.Json adds objects to a collection even if the property has no setter. System.Text.Json ignoruje właściwości, które nie mają metod ustawiających.System.Text.Json ignores properties that don't have setters. Te funkcje mogą zapewniać konwertery niestandardowe.Custom converters can provide this functionality.

Scenariusze, które nie są obecnie obsługiwane przez JsonSerializerScenarios that JsonSerializer currently doesn't support

W poniższych scenariuszach obejścia nie są praktyczne ani możliwe.For the following scenarios, workarounds are not practical or possible. Jeśli korzystasz z tych funkcji Newtonsoft.Json, migracja nie będzie możliwa bez znaczących zmian.If you rely on these Newtonsoft.Json features, migration will not be possible without significant changes.

Zachowaj odwołania do obiektów i pętle obsługiPreserve object references and handle loops

Domyślnie Newtonsoft.Json serializacji według wartości.By default, Newtonsoft.Json serializes by value. Na przykład jeśli obiekt zawiera dwie właściwości, które zawierają odwołanie do tego samego obiektu Person, wartości właściwości tego obiektu Person są zduplikowane w kodzie JSON.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 ma PreserveReferencesHandling ustawienia JsonSerializerSettings, które umożliwiają serializację przez odwołanie:Newtonsoft.Json has a PreserveReferencesHandling setting on JsonSerializerSettings that lets you serialize by reference:

  • Metadane identyfikatora są dodawane do pliku JSON utworzonego dla pierwszego obiektu Person.An identifier metadata is added to the JSON created for the first Person object.
  • KOD JSON tworzony dla drugiego obiektu Person zawiera odwołanie do tego identyfikatora zamiast wartości właściwości.The JSON that is created for the second Person object contains a reference to that identifier instead of property values.

Newtonsoft.Json ma także ReferenceLoopHandling ustawienie, które umożliwia ignorowanie odwołań cyklicznych zamiast zgłaszania wyjątku.Newtonsoft.Json also has a ReferenceLoopHandling setting that lets you ignore circular references rather than throw an exception.

System.Text.Json obsługuje serializacji tylko przez wartość i zgłasza wyjątek dla odwołań cyklicznych.System.Text.Json only supports serialization by value and throws an exception for circular references.

Atrybuty System. Runtime. SerializationSystem.Runtime.Serialization attributes

System.Text.Json nie obsługuje atrybutów z przestrzeni nazw System.Runtime.Serialization, takich jak DataMemberAttribute i IgnoreDataMemberAttribute.System.Text.Json doesn't support attributes from the System.Runtime.Serialization namespace, such as DataMemberAttribute and IgnoreDataMemberAttribute.

Liczby ósemkoweOctal numbers

Newtonsoft.Json traktuje liczby z zerem wiodącym jako liczba ósemkowa.Newtonsoft.Json treats numbers with a leading zero as octal numbers. System.Text.Json nie zezwala na zera wiodące, ponieważ Specyfikacja RFC 8259 nie zezwala.System.Text.Json doesn't allow leading zeroes because the RFC 8259 specification doesn't allow them.

MissingMemberHandlingMissingMemberHandling

Newtonsoft.Json można skonfigurować do zgłaszania wyjątków podczas deserializacji, jeśli dane JSON zawierają właściwości, których brakuje w typie docelowym.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 ignoruje dodatkowe właściwości w formacie JSON, z wyjątkiem sytuacji, gdy jest używany atrybut [JsonExtensionData].System.Text.Json ignores extra properties in the JSON, except when you use the [JsonExtensionData] attribute. Nie istnieje obejście dla brakującej funkcji członkowskiej.There's no workaround for the missing member feature.

TraceWriterTraceWriter

Newtonsoft.Json umożliwia debugowanie przy użyciu TraceWriter do wyświetlania dzienników generowanych przez serializacji lub deserializacji.Newtonsoft.Json lets you debug by using a TraceWriter to view logs that are generated by serialization or deserialization. System.Text.Json nie wykonuje rejestrowania.System.Text.Json doesn't do logging.

JsonDocument i Jsonelement w porównaniu do JToken (np. JObject, JArray)JsonDocument and JsonElement compared to JToken (like JObject, JArray)

System.Text.Json.JsonDocument umożliwia analizowanie i kompilowanie Document Object Model (DOM) tylko do odczytu z istniejących ładunków JSON.System.Text.Json.JsonDocument provides the ability to parse and build a read-only Document Object Model (DOM) from existing JSON payloads. DOM zapewnia losowy dostęp do danych w ładunku JSON.The DOM provides random access to data in a JSON payload. Do elementów JSON, które tworzą ładunek, można uzyskać dostęp za pośrednictwem typu JsonElement.The JSON elements that compose the payload can be accessed via the JsonElement type. Typ JsonElement udostępnia interfejsy API do konwersji tekstu JSON na popularne typy .NET.The JsonElement type provides APIs to convert JSON text to common .NET types. JsonDocument uwidacznia Właściwość RootElement.JsonDocument exposes a RootElement property.

JsonDocument jest interfejs IDisposableJsonDocument is IDisposable

JsonDocument kompiluje widok danych w pamięci w buforze puli.JsonDocument builds an in-memory view of the data into a pooled buffer. W związku z tym, w przeciwieństwie do JObject lub JArray z Newtonsoft.Json, typ JsonDocument implementuje IDisposable i musi być używany wewnątrz bloku using.Therefore, unlike JObject or JArray from Newtonsoft.Json, the JsonDocument type implements IDisposable and needs to be used inside a using block.

Zwróć JsonDocument z interfejsu API, jeśli chcesz przenieść własność okresu istnienia i usunąć odpowiedzialność do obiektu wywołującego.Only return a JsonDocument from your API if you want to transfer lifetime ownership and dispose responsibility to the caller. W większości przypadków nie jest to konieczne.In most scenarios, that isn't necessary. Jeśli obiekt wywołujący musi współdziałać z całym dokumentem JSON, zwróć Clone RootElement, który jest JsonElement.If the caller needs to work with the entire JSON document, return the Clone of the RootElement, which is a JsonElement. Jeśli obiekt wywołujący musi pracować z określonym elementem w dokumencie JSON, zwróć Clone tego JsonElement.If the caller needs to work with a particular element within the JSON document, return the Clone of that JsonElement. Jeśli powrócisz RootElement lub element podrzędny bezpośrednio bez tworzenia Clone, obiekt wywołujący nie będzie w stanie uzyskać dostępu do zwróconej JsonElement po usunięciu JsonDocument, do którego należy.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.

Oto przykład, który wymaga wprowadzenia Clone: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();
    }
}

Poprzedni kod oczekuje JsonElement, który zawiera właściwość fileName.The preceding code expects a JsonElement that contains a fileName property. Otwiera plik JSON i tworzy JsonDocument.It opens the JSON file and creates a JsonDocument. Metoda zakłada, że obiekt wywołujący chce współpracować z całym dokumentem, dlatego zwraca Clone RootElement.The method assumes that the caller wants to work with the entire document, so it returns the Clone of the RootElement.

Jeśli zostanie wyświetlony JsonElement i zwróci element podrzędny, nie trzeba zwracać Clone elementu podrzędnego.If you receive a JsonElement and are returning a sub-element, it's not necessary to return a Clone of the sub-element. Obiekt wywołujący jest odpowiedzialny za utrzymanie aktywności JsonDocument, do której należy JsonElement zakończono.The caller is responsible for keeping alive the JsonDocument that the passed-in JsonElement belongs to. Na przykład:For example:

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

JsonDocument jest tylko do odczytuJsonDocument is read-only

System.Text.Json DOM nie może dodawać, usuwać ani modyfikować elementów JSON.The System.Text.Json DOM can't add, remove, or modify JSON elements. Ta metoda została zaprojektowana w taki sposób, aby zwiększyć wydajność i zmniejszyć alokacje do analizy wspólnych rozmiarów ładunków JSON (czyli < 1 MB).It's designed this way for performance and to reduce allocations for parsing common JSON payload sizes (that is, < 1 MB). Jeśli w scenariuszu obecnie jest używany modyfikowalny DOM, jedno z następujących obejść może być wykonalne:If your scenario currently uses a modifiable DOM, one of the following workarounds might be feasible:

  • Aby skompilować JsonDocument od podstaw (to oznacza, że bez przekazywania istniejącego ładunku JSON do metody Parse), Napisz tekst JSON przy użyciu Utf8JsonWriter i Przeanalizuj dane wyjściowe z tego, aby utworzyć nowy JsonDocument.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.
  • Aby zmodyfikować istniejące JsonDocument, należy użyć go do zapisania tekstu JSON, wprowadzenia zmian podczas pisania i przeanalizowania danych wyjściowych, aby utworzyć nowe JsonDocument.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.
  • Aby scalić istniejące dokumenty JSON, równoważne JObject.Merge lub JContainer.Merge interfejsów API z Newtonsoft.Json, zobacz ten problemw serwisie GitHub.To merge existing JSON documents, equivalent to the JObject.Merge or JContainer.Merge APIs from Newtonsoft.Json, see this GitHub issue.

Jsonelement jest strukturą UnionJsonElement is a union struct

JsonDocument uwidacznia RootElement jako właściwość typu JsonElement, która jest Unią, typ struktury, która obejmuje dowolny element JSON.JsonDocument exposes the RootElement as a property of type JsonElement, which is a union, struct type that encompasses any JSON element. Newtonsoft.Json używa dedykowanych typów hierarchicznych, takich jak JObject,JArray, JTokeni tak dalej.Newtonsoft.Json uses dedicated hierarchical types like JObject,JArray, JToken, and so forth. JsonElement to elementy, które można wyszukać i wyliczyć, i można użyć JsonElement do zmaterializowania elementów JSON do typów .NET.JsonElement is what you can search and enumerate over, and you can use JsonElement to materialize JSON elements into .NET types.

Jak wyszukiwać element JsonDocument i Jsonelement dla elementów podrzędnychHow to search a JsonDocument and JsonElement for sub-elements

Wyszukuje tokeny JSON przy użyciu JObject lub JArray z Newtonsoft.Json jest stosunkowo szybka, ponieważ są wyszukiwaniemi w słowniku.Searches for JSON tokens using JObject or JArray from Newtonsoft.Json tend to be relatively fast because they're lookups in some dictionary. Zgodnie z porównaniem program wyszukuje JsonElement wymagające wyszukania właściwości i dlatego jest stosunkowo wolny (na przykład przy użyciu 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 zaprojektowano w celu zminimalizowania początkowego czasu analizy zamiast czasu wyszukiwania.System.Text.Json is designed to minimize initial parse time rather than lookup time. W związku z tym należy stosować następujące podejścia do optymalizowania wydajności podczas wyszukiwania za pomocą obiektu JsonDocument:Therefore, use the following approaches to optimize performance when searching through a JsonDocument object:

  • Użyj wbudowanych modułów wyliczających (EnumerateArray i EnumerateObject), zamiast tworzyć własne indeksowania lub pętle.Use the built-in enumerators (EnumerateArray and EnumerateObject) rather than doing your own indexing or loops.
  • Nie wykonuj wyszukiwania sekwencyjnego na całej JsonDocument za pośrednictwem każdej właściwości przy użyciu RootElement.Don't do a sequential search on the whole JsonDocument through every property by using RootElement. Zamiast tego należy szukać obiektów zagnieżdżonych JSON w oparciu o znaną strukturę danych JSON.Instead, search on nested JSON objects based on the known structure of the JSON data. Na przykład jeśli szukasz właściwości Grade w obiektach Student, pętla przez Student obiektów i Pobierz wartość Grade dla każdego, zamiast przeszukiwać wszystkie JsonElement obiekty, szukając Grade właściwości.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. Wykonanie tych czynności spowoduje niepotrzebne przekazanie tych samych danych.Doing the latter will result in unnecessary passes over the same data.

Aby uzyskać przykład kodu, zobacz Korzystanie z JsonDocument w celu uzyskania dostępu do danych.For a code example, see Use JsonDocument for access to data.

Utf8JsonReader w porównaniu do JsonTextReaderUtf8JsonReader compared to JsonTextReader

System.Text.Json.Utf8JsonReader jest wysoce wydajnym, niskim alokacją, czytnikiem tylko do przodu dla tekstu JSON zakodowanego w formacie UTF-8, Odczytaj z ReadOnlySpan<bajt > lub ReadOnlySequence<bajt >.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>. Utf8JsonReader jest typem niskiego poziomu, który może służyć do tworzenia niestandardowych analizatorów i deserializacji.The Utf8JsonReader is a low-level type that can be used to build custom parsers and deserializers.

W poniższych sekcjach opisano zalecane wzorce programowania do korzystania z Utf8JsonReader.The following sections explain recommended programming patterns for using Utf8JsonReader.

Utf8JsonReader jest strukturą refUtf8JsonReader is a ref struct

Ponieważ typ Utf8JsonReader jest strukturą ref, ma pewne ograniczenia.Because the Utf8JsonReader type is a ref struct, it has certain limitations. Na przykład nie można go zapisać jako pola w klasie lub strukturze innej niż struktura ref.For example, it can't be stored as a field on a class or struct other than a ref struct. Aby osiągnąć wysoką wydajność, ten typ musi być ref struct, ponieważ musi buforować wejściowe ReadOnlySpan<bajt >, który sam jest strukturą ref.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. Ponadto ten typ jest modyfikowalny, ponieważ zawiera stan.In addition, this type is mutable since it holds state. W związku z tym Przekaż go przez odwołanie , a nie przez wartość.Therefore, pass it by ref rather than by value. Przekazanie go przez wartość spowoduje skopiowanie struktury i zmiana stanu nie będzie widoczna dla obiektu wywołującego.Passing it by value would result in a struct copy and the state changes would not be visible to the caller. Różni się to od Newtonsoft.Json, ponieważ Newtonsoft.Json JsonTextReader jest klasą.This differs from Newtonsoft.Json since the Newtonsoft.Json JsonTextReader is a class. Aby uzyskać więcej informacji o sposobach korzystania z struktur ref, zobacz Zapisywanie bezpiecznego i C# wydajnego kodu.For more information about how to use ref structs, see Write safe and efficient C# code.

Odczytaj tekst UTF-8Read UTF-8 text

Aby osiągnąć najlepszą możliwą wydajność przy użyciu Utf8JsonReader, Odczytaj ładunki JSON już zakodowane jako tekst UTF-8, a nie jako ciągi UTF-16.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. Aby zapoznać się z przykładem kodu, zobacz filtrowanie danych za pomocą Utf8JsonReader.For a code example, see Filter data using Utf8JsonReader.

Odczytaj przy użyciu strumienia lub PipeReaderRead with a Stream or PipeReader

Utf8JsonReader obsługuje odczytywanie z zakodowanego w formacie UTF-8 ReadOnlySpan<bajt > lub ReadOnlySequence<bajt > (który jest wynikiem odczytu z PipeReader).The Utf8JsonReader supports reading from a UTF-8 encoded ReadOnlySpan<byte> or ReadOnlySequence<byte> (which is the result of reading from a PipeReader).

W przypadku odczytu synchronicznego można odczytać ładunek JSON do końca strumienia w tablicy bajtów i przekazać go do czytnika.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. Do odczytywania z ciągu (zakodowanego jako UTF-16) Wywołaj UTF8.GetBytesFor reading from a string (which is encoded as UTF-16), call UTF8.GetBytes Aby najpierw transkodowanie ciąg do tablicy bajtów zakodowanych w formacie UTF-8.to first transcode the string to a UTF-8 encoded byte array. Następnie Przekaż go do Utf8JsonReader.Then pass that to the Utf8JsonReader.

Ponieważ Utf8JsonReader traktuje dane wejściowe jako tekst JSON, znacznik kolejności bajtów UTF-8 jest uznawany za nieprawidłowy kod JSON.Since the Utf8JsonReader considers the input to be JSON text, a UTF-8 byte order mark (BOM) is considered invalid JSON. Obiekt wywołujący musi odfiltrować to wyjście przed przekazaniem danych do czytnika.The caller needs to filter that out before passing the data to the reader.

Aby zapoznać się z przykładami kodu, zobacz use Utf8JsonReader.For code examples, see Use Utf8JsonReader.

Odczytaj z ReadOnlySequence wiele segmentówRead with multi-segment ReadOnlySequence

Jeśli dane wejściowe JSON to ReadOnlySpan<bajt >, do każdego elementu JSON można uzyskać dostęp z właściwości ValueSpan w czytniku podczas przechodzenia przez pętlę odczytu.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. Jeśli jednak dane wejściowe to ReadOnlySequence<bajty > (który jest wynikiem odczytu z PipeReader), niektóre elementy JSON mogą obsłużyć wiele segmentów obiektu ReadOnlySequence<byte>.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. Te elementy byłyby niedostępne z ValueSpan w ciągłym bloku pamięci.These elements would not be accessible from ValueSpan in a contiguous memory block. Zamiast tego, jeśli masz ReadOnlySequence<byte> jako dane wejściowe, sondowanie właściwości HasValueSequence w czytniku, aby ustalić, jak uzyskać dostęp do bieżącego elementu JSON.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. Oto zalecany wzorzec:Here's a recommended pattern:

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

Użyj ValueTextEquals do wyszukiwania nazw właściwościUse ValueTextEquals for property name lookups

Nie używaj ValueSpan do przeszukiwania bajtów po bajcie, wywołując SequenceEqual do wyszukiwania nazw właściwości.Don't use ValueSpan to do byte-by-byte comparisons by calling SequenceEqual for property name lookups. Wywołaj ValueTextEquals zamiast tego, ponieważ ta metoda nie ma żadnych znaków, które są wyprowadzane w formacie JSON.Call ValueTextEquals instead, because that method unescapes any characters that are escaped in the JSON. Oto przykład, który pokazuje, jak wyszukiwać właściwość o nazwie "name":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;
    }

Odczytywanie wartości null w typach wartości nullRead null values into nullable value types

Newtonsoft.Json udostępnia interfejsy API, które zwracają Nullable<T>, takie jak ReadAsBoolean, które obsługują Null TokenType przez zwrócenie bool?.Newtonsoft.Json provides APIs that return Nullable<T>, such as ReadAsBoolean, which handles a Null TokenType for you by returning a bool?. Wbudowane interfejsy API System.Text.Json zwracają tylko typy wartości niedopuszczające wartości null.The built-in System.Text.Json APIs return only non-nullable value types. Na przykład Utf8JsonReader.GetBoolean zwraca bool.For example, Utf8JsonReader.GetBoolean returns a bool. Zgłasza wyjątek, jeśli odnajdzie Null w formacie JSON.It throws an exception if it finds Null in the JSON. W poniższych przykładach pokazano dwa sposoby obsługi wartości null, jeden przez zwrócenie typu wartości null i jednego przez zwrócenie wartości domyślnej: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();
}

Wiele elementów docelowychMulti-targeting

Jeśli musisz nadal używać Newtonsoft.Json dla pewnych platform docelowych, możesz wybrać wiele implementacji i mieć dwie implementacje.If you need to continue to use Newtonsoft.Json for certain target frameworks, you can multi-target and have two implementations. Nie jest to jednak proste i wymagało pewnego #ifdefs i duplikowania źródła.However, this is not trivial and would require some #ifdefs and source duplication. Jednym ze sposobów udostępniania możliwie największej ilości kodu jest utworzenie otoki ref struct wokół Utf8JsonReader i Newtonsoft.Json JsonTextReader.One way to share as much code as possible is to create a ref struct wrapper around Utf8JsonReader and Newtonsoft.Json JsonTextReader. Ta otoka umożliwia ujednolicenie obszaru powierzchni publicznej podczas izolowania różnic behawioralnych.This wrapper would unify the public surface area while isolating the behavioral differences. Dzięki temu można izolować zmiany w odniesieniu do konstrukcji typu wraz z przekazywaniem nowego typu dookoła przez odwołanie.This lets you isolate the changes mainly to the construction of the type, along with passing the new type around by reference. Jest to wzorzec, który jest następujący :This is the pattern that the Microsoft.Extensions.DependencyModel library follows:

Utf8JsonWriter w porównaniu do JsonTextWriterUtf8JsonWriter compared to JsonTextWriter

System.Text.Json.Utf8JsonWriter to wysoce wydajny sposób pisania zakodowanego tekstu JSON w formacie UTF-8 ze wspólnych typów platformy .NET, takich jak String, Int32i DateTime.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. Składnik zapisywania jest typu niskiego poziomu, który może służyć do tworzenia serializatorów niestandardowych.The writer is a low-level type that can be used to build custom serializers.

W poniższych sekcjach opisano zalecane wzorce programowania do korzystania z Utf8JsonWriter.The following sections explain recommended programming patterns for using Utf8JsonWriter.

Napisz z tekstem UTF-8Write with UTF-8 text

Aby osiągnąć najlepszą możliwą wydajność przy użyciu Utf8JsonWriter, Zapisz ładunki JSON już zakodowane jako tekst UTF-8, a nie jako ciągi UTF-16.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. Użyj JsonEncodedText, aby buforować i wstępnie kodować znane nazwy i wartości właściwości ciągów jako elementy statyczne i przekazać je do składnika zapisywania zamiast używać literałów ciągów w formacie UTF-16.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. Jest to szybsze niż buforowanie i korzysta z tablic bajtowych UTF-8.This is faster than caching and using UTF-8 byte arrays.

Takie podejście działa również, jeśli trzeba wykonać niestandardowe ucieczki.This approach also works if you need to do custom escaping. System.Text.Json nie pozwala na wyłączenie ucieczki podczas pisania ciągu.System.Text.Json doesn't let you disable escaping while writing a string. Można jednak przekazać własne JavaScriptEncoder niestandardowe jako opcję składnika zapisywania lub utworzyć własne JsonEncodedText, które używają JavascriptEncoder do wykonywania ucieczki, a następnie napisać JsonEncodedText zamiast ciągu.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. Aby uzyskać więcej informacji, zobacz Dostosowywanie kodowania znaków.For more information, see Customize character encoding.

Zapisz nieprzetworzone wartościWrite raw values

Metoda Newtonsoft.Json WriteRawValue zapisuje nieprzetworzony kod JSON, w którym oczekiwana jest wartość.The Newtonsoft.Json WriteRawValue method writes raw JSON where a value is expected. System.Text.Json nie ma bezpośredniego odpowiednika, ale jest to obejście, które gwarantuje, że jest zapisany tylko prawidłowy kod JSON: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);

Dostosowywanie ucieczki znakówCustomize character escaping

Ustawienie StringEscapeHandling JsonTextWriter oferuje opcje ucieczki wszystkich znaków spoza zestawu ASCII lub znaków HTML.The StringEscapeHandling setting of JsonTextWriter offers options to escape all non-ASCII characters or HTML characters. Domyślnie Utf8JsonWriter wyprowadza wszystkie znaki inne niż ASCII i html.By default, Utf8JsonWriter escapes all non-ASCII and HTML characters. To anulowanie jest wykonywane w celu zapewnienia bezpieczeństwa ze względu na ochronę.This escaping is done for defense-in-depth security reasons. Aby określić inne zasady ucieczki, Utwórz JavaScriptEncoder i ustaw JsonWriterOptions.Encoder.To specify a different escaping policy, create a JavaScriptEncoder and set JsonWriterOptions.Encoder. Aby uzyskać więcej informacji, zobacz Dostosowywanie kodowania znaków.For more information, see Customize character encoding.

Dostosuj format JSONCustomize JSON format

JsonTextWriter obejmuje następujące ustawienia, dla których Utf8JsonWriter nie ma odpowiednika:JsonTextWriter includes the following settings, for which Utf8JsonWriter has no equivalent:

  • Wcięcia — określa liczbę znaków do wcięcia.Indentation - Specifies how many characters to indent. Utf8JsonWriter zawsze wykonuje wcięcie z 2 znakami.Utf8JsonWriter always does 2-character indentation.
  • IndentChar — określa znak do użycia w przypadku wcięcia.IndentChar - Specifies the character to use for indentation. Utf8JsonWriter zawsze używa białych znaków.Utf8JsonWriter always uses whitespace.
  • QuoteChar — określa znak, który ma być używany do otaczania wartości ciągu.QuoteChar - Specifies the character to use to surround string values. Utf8JsonWriter zawsze używa podwójnych cudzysłowów.Utf8JsonWriter always uses double quotes.
  • Quote -określa, czy należy ująć nazwy właściwości z cudzysłowami.QuoteName - Specifies whether or not to surround property names with quotes. Utf8JsonWriter zawsze ujmuje je w cudzysłowy.Utf8JsonWriter always surrounds them with quotes.

Nie istnieją obejścia, które pozwolą dostosować kod JSON utworzony przez Utf8JsonWriter w taki sposób.There are no workarounds that would let you customize the JSON produced by Utf8JsonWriter in these ways.

Zapisz wartości nullWrite null values

Aby zapisać wartości null przy użyciu Utf8JsonWriter, wywołaj:To write null values by using Utf8JsonWriter, call:

  • WriteNull zapisać pary klucz-wartość z wartością null jako wartością.WriteNull to write a key-value pair with null as the value.
  • WriteNullValue zapisać wartości null jako elementu tablicy JSON.WriteNullValue to write null as an element of a JSON array.

Dla właściwości String, jeśli ciąg ma wartość null, WriteString i WriteStringValue są równoważne WriteNull i WriteNullValue.For a string property, if the string is null, WriteString and WriteStringValue are equivalent to WriteNull and WriteNullValue.

Zapis wartości TimeSpan, URI lub charWrite Timespan, Uri, or char values

JsonTextWriter zapewnia WriteValue metod dla wartości TimeSpan, URIi char .JsonTextWriter provides WriteValue methods for TimeSpan, Uri, and char values. Utf8JsonWriter nie ma równoważnych metod.Utf8JsonWriter doesn't have equivalent methods. Zamiast tego sformatuj te wartości jako ciągi (przez wywołanie ToString(), na przykład) i wywołań WriteStringValue.Instead, format these values as strings (by calling ToString(), for example) and call WriteStringValue.

Wiele elementów docelowychMulti-targeting

Jeśli musisz nadal używać Newtonsoft.Json dla pewnych platform docelowych, możesz wybrać wiele implementacji i mieć dwie implementacje.If you need to continue to use Newtonsoft.Json for certain target frameworks, you can multi-target and have two implementations. Nie jest to jednak proste i wymagało pewnego #ifdefs i duplikowania źródła.However, this is not trivial and would require some #ifdefs and source duplication. Jednym ze sposobów udostępniania możliwie największej ilości kodu jest utworzenie otoki wokół Utf8JsonWriter i Newtonsoft JsonTextWriter.One way to share as much code as possible is to create a wrapper around Utf8JsonWriter and Newtonsoft JsonTextWriter. Ta otoka umożliwia ujednolicenie obszaru powierzchni publicznej podczas izolowania różnic behawioralnych.This wrapper would unify the public surface area while isolating the behavioral differences. Dzięki temu można izolować zmiany głównie do konstrukcji typu.This lets you isolate the changes mainly to the construction of the type. Biblioteka Microsoft. Extensions. DependencyModel :Microsoft.Extensions.DependencyModel library follows:

Dodatkowe zasobyAdditional resources