Porównaj Newtonsoft.Json z elementami System.Text.Jsoni przeprowadź migrację do System.Text.Json

W tym artykule pokazano, jak przeprowadzić migrację z Newtonsoft.Json programu do programu System.Text.Json.

System.Text.Json Przestrzeń nazw zapewnia funkcje serializacji do i deserializacji z pliku JavaScript Object Notation (JSON). Biblioteka jest zawarta System.Text.Json w środowisku uruchomieniowym dla platformy .NET Core 3.1 i nowszych wersji. W przypadku innych platform docelowych zainstaluj System.Text.Json pakiet NuGet. Pakiet obsługuje:

  • .NET Standard 2.0 i nowsze wersje
  • .NET Framework 4.7.2 i nowsze wersje
  • .NET Core 2.0, 2.1 i 2.2

System.Text.Json koncentruje się głównie na wydajności, bezpieczeństwie i zgodności ze standardami. Ma pewne kluczowe różnice w zachowaniu domyślnym i nie ma na celu parzystości funkcji z Newtonsoft.Json. W przypadku niektórych scenariuszy System.Text.Json obecnie nie ma wbudowanych funkcji, ale istnieją zalecane obejścia. W przypadku innych scenariuszy obejścia są niepraktyczne.

Inwestujemy w dodanie funkcji, które najczęściej były żądane. Jeśli aplikacja zależy od brakującej funkcji, rozważ zgłoszenie problemu w repozytorium dotnet/runtime w usłudze GitHub, aby dowiedzieć się, czy można dodać obsługę danego scenariusza. Zobacz epicki problem nr 43620 , aby dowiedzieć się, co jest już planowane.

Większość tego artykułu dotyczy sposobu korzystania z interfejsu JsonSerializer API, ale zawiera również wskazówki dotyczące sposobu używania JsonDocument (który reprezentuje model obiektów dokumentów lub MODELU DOM), Utf8JsonReaderi Utf8JsonWriter typów.

W języku Visual Basic nie można użyć elementu Utf8JsonReader, co oznacza również, że nie można pisać konwerterów niestandardowych. Większość przedstawionych tutaj obejść wymaga pisania konwerterów niestandardowych. Konwerter niestandardowy można napisać w języku C# i zarejestrować go w projekcie języka Visual Basic. Aby uzyskać więcej informacji, zobacz Obsługa języka Visual Basic.

Tabela różnic między Newtonsoft.Json i System.Text.Json

W poniższej tabeli wymieniono Newtonsoft.Json funkcje i System.Text.Json odpowiedniki. Odpowiedniki należą do następujących kategorii:

  • ✔️ Obsługiwane przez wbudowane funkcje. Uzyskanie podobnego zachowania System.Text.Json może wymagać użycia atrybutu lub opcji globalnej.
  • ⚠✔ Nieobsługiwane, ale możliwe jest obejście. Obejścia to konwertery niestandardowe, które mogą nie zapewniać pełnej parzystości z funkcjami Newtonsoft.Json . W przypadku niektórych z nich przykładowy kod jest dostarczany jako przykłady. Jeśli korzystasz z tych Newtonsoft.Json funkcji, migracja będzie wymagać modyfikacji modeli obiektów platformy .NET lub innych zmian w kodzie.
  • ❌ Nieobsługiwane, a obejście nie jest praktyczne ani możliwe. Jeśli korzystasz z tych Newtonsoft.Json funkcji, migracja nie będzie możliwa bez istotnych zmian.
Funkcja systemu Newtonsoft.Json System.Text.Json Równoważne
Deserializacji bez uwzględniania wielkości liter domyślnie ✔️ Ustawienie globalne PropertyNameCaseInsensitive
Nazwy właściwości camel-case ✔️ Ustawienie globalne PropertyNamingPolicy
Minimalny znak ucieczki ✔️ Ścisłe znaki ucieczki, konfigurowalne
NullValueHandling.Ignore ustawienie globalne ✔️ Opcja globalna DefaultIgnoreCondition
Zezwalaj na komentarze ✔️ Ustawienie globalne ReadCommentHandling
Zezwalaj na końcowe przecinki ✔️ Ustawienie globalne AllowTrailingCommas
Rejestracja konwertera niestandardowego ✔️ Kolejność pierwszeństwa różni się
Domyślnie nie ma maksymalnej głębokości ✔️ Domyślna maksymalna głębokość 64, konfigurowalna
PreserveReferencesHandling ustawienie globalne ✔️ Ustawienie globalne ReferenceHandling
Serializowanie lub deserializowanie liczb w cudzysłowie ✔️ NumberHandling ustawienia globalnego, atrybut [JsonNumberHandling]
Deserializowanie do niezmiennych klas i struktur ✔️ JsonConstructor, rekordy języka C# 9
Obsługa pól ✔️ Ustawienie globalne IncludeFields, atrybut [JsonInclude]
DefaultValueHandling ustawienie globalne ✔️ Ustawienie globalne DefaultIgnoreCondition
NullValueHandling ustawienie włączone [JsonProperty] ✔️ Atrybut JsonIgnore
DefaultValueHandling ustawienie włączone [JsonProperty] ✔️ Atrybut JsonIgnore
Deserializowanie Dictionary za pomocą klucza innego niż ciąg ✔️ Obsługiwane
Obsługa zestawów właściwości innych niż publiczne i metody pobierające ✔️ Atrybut JsonInclude
Atrybut [JsonConstructor] ✔️ [JsonConstructor] , atrybut
ReferenceLoopHandling ustawienie globalne ✔️ Ustawienie globalne ReferenceHandling
Wywołania zwrotne ✔️ Wywołania zwrotne
NaN, Infinity, -Infinity ✔️ Obsługiwane
Requiredustawienie atrybutu [JsonProperty] ✔️ [JsonRequired] atrybut i wymagany modyfikator języka C#
DefaultContractResolver aby zignorować właściwości ✔️ DefaultJsonTypeInfoResolver, klasa
Serializacja polimorficzna ✔️ [JsonDerivedType] , atrybut
Deserializacja polimorficzna ✔️ Dyskryminator typów dla atrybutu [JsonDerivedType]
Obsługa szerokiego zakresu typów ⚠✔ Niektóre typy wymagają niestandardowych konwerterów
Deserializowanie wnioskowania typu do object właściwości ⚠✔ Nieobsługiwane, obejście, próbka
Deserializowanie literału JSON null do typów wartości innych niż null ⚠✔ Nieobsługiwane, obejście, próbka
DateTimeZoneHandling, DateFormatString ustawienia ⚠✔ Nieobsługiwane, obejście, próbka
Metoda JsonConvert.PopulateObject ⚠✔ Nieobsługiwane, obejście
ObjectCreationHandling ustawienie globalne ⚠✔ Nieobsługiwane, obejście
Dodawanie do kolekcji bez elementów ustawiających ⚠️ Nieobsługiwane, obejście
Nazwy właściwości snake-case ⚠️ Nieobsługiwane, obejście
Obsługa System.Runtime.Serialization atrybutów Nieobsługiwane
MissingMemberHandling ustawienie globalne Nieobsługiwane
Zezwalaj na nazwy właściwości bez cudzysłowów Nieobsługiwane
Zezwalaj na pojedyncze cudzysłowy wokół wartości ciągu Nieobsługiwane
Zezwalaj na wartości JSON innych niż ciąg dla właściwości ciągu Nieobsługiwane
TypeNameHandling.All ustawienie globalne Nieobsługiwane
Obsługa JsonPath zapytań Nieobsługiwane
Konfigurowalne limity Nieobsługiwane
Funkcja systemu Newtonsoft.Json System.Text.Json Równoważne
Deserializacji bez uwzględniania wielkości liter domyślnie ✔️ Ustawienie globalne WłaściwościNameCaseInsensitive
Nazwy właściwości camel-case ✔️ Ustawienie globalne PropertyNamingPolicy
Minimalny znak ucieczki ✔️ Ścisłe ucieczki znaków, konfigurowalne
NullValueHandling.Ignore ustawienie globalne ✔️ DefaultIgnoreCondition opcji globalnej
Zezwalaj na komentarze ✔️ ReadCommentHandling ustawienie globalne
Zezwalaj na końcowe przecinki ✔️ Ustawienie globalne AllowTrailingCommas
Rejestracja konwertera niestandardowego ✔️ Kolejność pierwszeństwa różni się
Domyślnie nie ma maksymalnej głębokości ✔️ Domyślna maksymalna głębokość 64, konfigurowalna
PreserveReferencesHandling ustawienie globalne ✔️ ReferenceHandling ustawienia globalnego
Serializowanie lub deserializacji liczb w cudzysłowie ✔️ NumberHandling ustawienia globalnego[JsonNumberHandling] atrybut
Deserializowanie do niezmiennych klas i struktur ✔️ Rekordy JsonConstructor, C# 9
Obsługa pól ✔️ Ustawienie globalne IncludeFields, atrybut [JsonInclude]
DefaultValueHandling ustawienie globalne ✔️ Ustawienie globalne DefaultIgnoreCondition
NullValueHandling ustawienie włączone [JsonProperty] ✔️ Atrybut JsonIgnore
DefaultValueHandling ustawienie włączone [JsonProperty] ✔️ Atrybut JsonIgnore
Deserializowanie Dictionary przy użyciu klucza innego niż ciąg ✔️ Obsługiwane
Obsługa zestawów właściwości innych niż publiczne i getters ✔️ Atrybut JsonInclude
Atrybut [JsonConstructor] ✔️ Atrybut [JsonConstructor]
ReferenceLoopHandling ustawienie globalne ✔️ ReferenceHandling ustawienia globalnego
Wywołania zwrotne ✔️ Wywołania zwrotne
NaN, Infinity, -Infinity ✔️ Obsługiwane
Obsługa szerokiego zakresu typów ⚠️ Niektóre typy wymagają konwerterów niestandardowych
Serializacja polimorficzna ⚠️ Nieobsługiwane, obejście, przykład
Deserializacji polimorficznej ⚠️ Nieobsługiwane, obejście, przykład
Deserializowanie wnioskowania typu do object właściwości ⚠️ Nieobsługiwane, obejście, przykład
Deserializowanie literału JSON null do typów wartości innych niż null ⚠️ Nieobsługiwane, obejście, przykład
Requiredustawienie atrybutu [JsonProperty] ⚠️ Nieobsługiwane, obejście, przykład
DefaultContractResolver aby zignorować właściwości ⚠️ Nieobsługiwane, obejście, przykład
DateTimeZoneHandling, DateFormatString ustawienia ⚠️ Nieobsługiwane, obejście, przykład
Metoda JsonConvert.PopulateObject ⚠️ Nieobsługiwane, obejście
ObjectCreationHandling ustawienie globalne ⚠️ Nieobsługiwane, obejście
Dodawanie do kolekcji bez zestawów ⚠️ Nieobsługiwane, obejście
Nazwy właściwości snake-case ⚠️ Nieobsługiwane, obejście
Obsługa System.Runtime.Serialization atrybutów Nieobsługiwane
MissingMemberHandling ustawienie globalne Nieobsługiwane
Zezwalaj na nazwy właściwości bez cudzysłowów Nieobsługiwane
Zezwalaj na pojedyncze cudzysłowy wokół wartości ciągu Nieobsługiwane
Zezwalaj na wartości JSON innych niż ciąg dla właściwości ciągu Nieobsługiwane
TypeNameHandling.All ustawienie globalne Nieobsługiwane
Obsługa JsonPath zapytań Nieobsługiwane
Konfigurowalne limity Nieobsługiwane
Funkcja systemu Newtonsoft.Json System.Text.Json Równoważne
Deserializacji bez uwzględniania wielkości liter domyślnie ✔️ Ustawienie globalne WłaściwościNameCaseInsensitive
Nazwy właściwości camel-case ✔️ Ustawienie globalne PropertyNamingPolicy
Minimalny znak ucieczki ✔️ Ścisłe ucieczki znaków, konfigurowalne
NullValueHandling.Ignore ustawienie globalne ✔️ IgnorullValues opcji globalnej
Zezwalaj na komentarze ✔️ ReadCommentHandling ustawienie globalne
Zezwalaj na końcowe przecinki ✔️ Ustawienie globalne AllowTrailingCommas
Rejestracja konwertera niestandardowego ✔️ Kolejność pierwszeństwa różni się
Domyślnie nie ma maksymalnej głębokości ✔️ Domyślna maksymalna głębokość 64, konfigurowalna
Obsługa szerokiego zakresu typów ⚠️ Niektóre typy wymagają konwerterów niestandardowych
Deserializacji ciągów jako liczb ⚠️ Nieobsługiwane, obejście, przykład
Deserializowanie Dictionary przy użyciu klucza innego niż ciąg ⚠️ Nieobsługiwane, obejście, przykład
Serializacja polimorficzna ⚠️ Nieobsługiwane, obejście, przykład
Deserializacji polimorficznej ⚠️ Nieobsługiwane, obejście, przykład
Deserializowanie wnioskowania typu do object właściwości ⚠️ Nieobsługiwane, obejście, przykład
Deserializowanie literału JSON null do typów wartości innych niż null ⚠️ Nieobsługiwane, obejście, przykład
Deserializowanie do niezmiennych klas i struktur ⚠️ Nieobsługiwane, obejście, przykład
Atrybut [JsonConstructor] ⚠️ Nieobsługiwane, obejście, przykład
Requiredustawienie atrybutu [JsonProperty] ⚠️ Nieobsługiwane, obejście, przykład
NullValueHandlingustawienie atrybutu [JsonProperty] ⚠️ Nieobsługiwane, obejście, przykład
DefaultValueHandlingustawienie atrybutu [JsonProperty] ⚠️ Nieobsługiwane, obejście, przykład
DefaultValueHandling ustawienie globalne ⚠️ Nieobsługiwane, obejście, przykład
DefaultContractResolver aby zignorować właściwości ⚠️ Nieobsługiwane, obejście, przykład
DateTimeZoneHandling, DateFormatString ustawienia ⚠️ Nieobsługiwane, obejście, przykład
Wywołania zwrotne ⚠️ Nieobsługiwane, obejście, przykład
Obsługa pól publicznych i niepublizowanych ⚠️ Nieobsługiwane, obejście
Obsługa zestawów właściwości innych niż publiczne i getters ⚠️ Nieobsługiwane, obejście
Metoda JsonConvert.PopulateObject ⚠️ Nieobsługiwane, obejście
ObjectCreationHandling ustawienie globalne ⚠️ Nieobsługiwane, obejście
Dodawanie do kolekcji bez zestawów ⚠️ Nieobsługiwane, obejście
Nazwy właściwości snake-case ⚠️ Nieobsługiwane, obejście
NaN, Infinity, -Infinity ⚠️ Nieobsługiwane, obejście
PreserveReferencesHandling ustawienie globalne Nieobsługiwane
ReferenceLoopHandling ustawienie globalne Nieobsługiwane
Obsługa System.Runtime.Serialization atrybutów Nieobsługiwane
MissingMemberHandling ustawienie globalne Nieobsługiwane
Zezwalaj na nazwy właściwości bez cudzysłowów Nieobsługiwane
Zezwalaj na pojedyncze cudzysłowy wokół wartości ciągu Nieobsługiwane
Zezwalaj na wartości JSON innych niż ciąg dla właściwości ciągu Nieobsługiwane
TypeNameHandling.All ustawienie globalne Nieobsługiwane
Obsługa JsonPath zapytań Nieobsługiwane
Konfigurowalne limity Nieobsługiwane

Nie jest to wyczerpująca lista Newtonsoft.Json funkcji. Lista zawiera wiele scenariuszy, które zostały żądane w problemach z usługą GitHub lub wpisami StackOverflow . Jeśli zaimplementujesz obejście jednego ze scenariuszy wymienionych w tym miejscu, które nie ma obecnie przykładowego kodu, a jeśli chcesz udostępnić rozwiązanie, wybierz pozycję Ta strona w sekcji Opinie w dolnej części tej strony. Spowoduje to utworzenie problemu w repozytorium GitHub tej dokumentacji i wyświetlenie go również w sekcji Opinie na tej stronie.

Różnice w domyślnym zachowaniu JsonSerializer w porównaniu do Newtonsoft.Json

System.Text.Json jest domyślnie rygorystyczna i unika odgadywania lub interpretacji w imieniu wywołującego, podkreślając deterministyczne zachowanie. Biblioteka została celowo zaprojektowana w ten sposób pod kątem wydajności i zabezpieczeń. Newtonsoft.Json jest domyślnie elastyczny. Ta podstawowa różnica w projekcie polega na wielu następujących konkretnych różnicach w zachowaniu domyślnym.

Deserializacji bez uwzględniania wielkości liter

Podczas deserializacji Newtonsoft.Json domyślnie jest dopasowywana nazwa właściwości bez uwzględniania wielkości liter. Wartość domyślna System.Text.Json jest uwzględniana w wielkości liter, co zapewnia lepszą wydajność, ponieważ wykonuje dokładne dopasowanie. Aby uzyskać informacje o sposobie dopasowywania bez uwzględniania wielkości liter, zobacz Dopasowywanie właściwości bez uwzględniania wielkości liter.

Jeśli używasz System.Text.Json pośrednio przy użyciu ASP.NET Core, nie musisz wykonywać żadnych czynności, aby uzyskać zachowanie, takie jak Newtonsoft.Json. ASP.NET Core określa ustawienia nazw właściwości camel-casing i dopasowywania bez uwzględniania wielkości liter, gdy używa System.Text.Json.

ASP.NET Core umożliwia również deserializowanie liczb cytowanych domyślnie.

Minimalny znak ucieczki

Podczas serializacji, Newtonsoft.Json jest stosunkowo permissive o pozwalając znaków bez ucieczki ich. Oznacza to, że nie zastępuje ich elementem \uxxxx , gdzie xxxx jest punktem kodu znaku. W przypadku ich ucieczki robi to, emitując znak przed znakiem \ (na przykład " staje się \"). System.Text.Json domyślnie zapewnia ochronę przed wykonywaniem skryptów między witrynami (XSS) lub atakami polegającymi na ujawnianiu informacji, a tym samym przy użyciu sekwencji sześciu znaków. System.Text.Json domyślnie nie zawiera wszystkich znaków innych niż ASCII, więc nie trzeba nic robić, jeśli używasz polecenia StringEscapeHandling.EscapeNonAscii w systemie Newtonsoft.Json. System.Text.Json Domyślnie znaki z uwzględnieniem kodu HTML są również ucieczką. Aby uzyskać informacje na temat zastępowania domyślnego System.Text.Json zachowania, zobacz Dostosowywanie kodowania znaków.

Komentarze

Podczas deserializacji Newtonsoft.Json domyślnie ignoruje komentarze w formacie JSON. Wartością domyślną System.Text.Json jest zgłaszanie wyjątków dla komentarzy, ponieważ specyfikacja RFC 8259 nie zawiera ich. Aby uzyskać informacje na temat zezwalania na komentarze, zobacz Zezwalaj na komentarze i końcowe przecinki.

Końcowe przecinki

Podczas deserializacji Newtonsoft.Json domyślnie ignoruje końcowe przecinki. Ignoruje również wiele końcowych przecinków (na przykład [{"Color":"Red"},{"Color":"Green"},,]). Wartością System.Text.Json domyślną jest zgłaszanie wyjątków dla końcowych przecinków, ponieważ specyfikacja RFC 8259 nie zezwala na nie. Aby uzyskać informacje na temat sposobu ich System.Text.Json akceptowania, zobacz Zezwalaj na komentarze i końcowe przecinki. Nie ma możliwości zezwalania na wiele końcowych przecinków.

Pierwszeństwo rejestracji konwertera

Pierwszeństwo Newtonsoft.Json rejestracji dla konwerterów niestandardowych jest następujące:

  • Atrybut we właściwości
  • Atrybut w typie
  • Kolekcja konwerterów

Ta kolejność oznacza, że konwerter niestandardowy w Converters kolekcji jest zastępowany przez konwerter zarejestrowany przez zastosowanie atrybutu na poziomie typu. Obie te rejestracje są zastępowane przez atrybut na poziomie właściwości.

Pierwszeństwo System.Text.Json rejestracji dla konwerterów niestandardowych jest inne:

  • Atrybut we właściwości
  • Converters Kolekcji
  • Atrybut w typie

Różnica polega na tym, że konwerter niestandardowy w Converters kolekcji zastępuje atrybut na poziomie typu. Celem tego porządku pierwszeństwa jest wprowadzenie zmian w czasie wykonywania zastąpić opcje czasu projektowania. Nie ma możliwości zmiany pierwszeństwa.

Aby uzyskać więcej informacji na temat rejestracji konwertera niestandardowego, zobacz Rejestrowanie konwertera niestandardowego.

Maksymalna głębokość

Najnowsza wersja programu Newtonsoft.Json ma domyślnie maksymalny limit głębokości wynoszący 64. System.Text.Json Ma również domyślny limit 64 i można go skonfigurować przez ustawienie JsonSerializerOptions.MaxDepth.

Jeśli używasz System.Text.Json pośrednio przy użyciu ASP.NET Core, domyślny maksymalny limit głębokości wynosi 32. Wartość domyślna jest taka sama jak w przypadku powiązania modelu i jest ustawiana w klasie JsonOptions.

Ciągi JSON (nazwy właściwości i wartości ciągów)

Podczas deserializacji Newtonsoft.Json akceptuje nazwy właściwości otoczone podwójnymi cudzysłowami, apostrofami lub bez cudzysłowów. Akceptuje wartości ciągów otoczone podwójnymi cudzysłowami lub apostrofami. Na przykład Newtonsoft.Json akceptuje następujący kod JSON:

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

System.Text.Json Akceptuje tylko nazwy właściwości i wartości ciągów w cudzysłowie, ponieważ ten format jest wymagany przez specyfikację RFC 8259 i jest jedynym formatem uważanym za prawidłowy kod JSON.

Wartość ujęta w apostrofy powoduje wyjątek JsonException z następującym komunikatem:

''' is an invalid start of a value.

Wartości inne niż ciągi dla właściwości ciągu

Newtonsoft.Json Akceptuje wartości inne niż ciągi, takie jak liczba lub literały true i false, do deserializacji do właściwości typu ciąg. Oto przykładowy kod JSON, który Newtonsoft.Json pomyślnie deserializuje do następującej klasy:

{
  "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 deserializuje wartości innych niż ciąg w właściwościach ciągu. Wartość nieciągnięta odebrana dla pola ciągu powoduje wyjątek JsonException z następującym komunikatem:

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

Scenariusze korzystające z narzędzia JsonSerializer

Niektóre z poniższych scenariuszy nie są obsługiwane przez wbudowane funkcje, ale możliwe są obejścia. Obejścia to konwertery niestandardowe, które mogą nie zapewniać pełnej parzystości z funkcjami Newtonsoft.Json . W przypadku niektórych z nich przykładowy kod jest dostarczany jako przykłady. Jeśli korzystasz z tych Newtonsoft.Json funkcji, migracja będzie wymagać modyfikacji modeli obiektów platformy .NET lub innych zmian w kodzie.

W przypadku niektórych z poniższych scenariuszy obejścia nie są praktyczne ani możliwe. Jeśli korzystasz z tych Newtonsoft.Json funkcji, migracja nie będzie możliwa bez istotnych zmian.

Zezwalanie na liczby w cudzysłowie lub zapisywanie ich w cudzysłowie

Newtonsoft.Json może serializować lub deserializować liczby reprezentowane przez ciągi JSON (w otoczeniu cudzysłowów). Na przykład może zaakceptować: {"DegreesCelsius":"23"} zamiast {"DegreesCelsius":23}. Aby włączyć to zachowanie w System.Text.Jsonsystemie , ustaw wartość JsonSerializerOptions.NumberHandlingWriteAsString lub AllowReadingFromString, lub użyj atrybutu [JsonNumberHandling].

Jeśli używasz System.Text.Json pośrednio przy użyciu ASP.NET Core, nie musisz wykonywać żadnych czynności, aby uzyskać zachowanie, takie jak Newtonsoft.Json. ASP.NET Core określa wartości domyślne sieci Web, gdy używa System.Text.Json, a wartości domyślne sieci Web zezwalają na liczby w cudzysłów.

Aby uzyskać więcej informacji, zobacz Zezwalanie na liczby lub zapisywanie ich w cudzysłowie.

Newtonsoft.Json może serializować lub deserializować liczby reprezentowane przez ciągi JSON (w otoczeniu cudzysłowów). Na przykład może zaakceptować: {"DegreesCelsius":"23"} zamiast {"DegreesCelsius":23}. Aby włączyć to zachowanie na System.Text.Json platformie .NET Core 3.1, zaimplementuj niestandardowy konwerter, tak jak w poniższym przykładzie. Konwerter obsługuje właściwości zdefiniowane jako long:

  • Serializuje je jako ciągi JSON.
  • Akceptuje liczby i liczby JSON w cudzysłowie podczas deserializacji.
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 (long.TryParse(reader.GetString(), out number))
                {
                    return number;
                }
            }

            return reader.GetInt64();
        }

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

Zarejestruj ten konwerter niestandardowy przy użyciu atrybutu dla poszczególnych long właściwości lub przez dodanie konwerteraConverters do kolekcji.

Określanie konstruktora do użycia podczas deserializacji

Atrybut Newtonsoft.Json[JsonConstructor] umożliwia określenie, który konstruktor ma być wywoływany podczas deserializacji do obiektu POCO.

System.Text.Jsonma również atrybut [JsonConstructor]. Aby uzyskać więcej informacji, zobacz Niezmienne typy i rekordy.

System.Text.Json Program .NET Core 3.1 obsługuje tylko konstruktory bez parametrów. Obejście tego problemu można wywołać niezależnie od tego, który konstruktor jest potrzebny w konwerterze niestandardowym. Zobacz przykład deserializacji do niezmiennych klas i struktur.

Warunkowo ignoruj właściwość

Newtonsoft.Json Program ma kilka sposobów warunkowego ignorowania właściwości w przypadku serializacji lub deserializacji:

  • DefaultContractResolver Umożliwia wybranie właściwości do uwzględnienia lub zignorowania na podstawie dowolnych kryteriów.
  • Ustawienia NullValueHandling i DefaultValueHandlingJsonSerializerSettings umożliwiają określenie, że wszystkie właściwości null-value lub default-value powinny być ignorowane.
  • Ustawienia NullValueHandling i DefaultValueHandling w atrybucie [JsonProperty] umożliwiają określenie poszczególnych właściwości, które mają być ignorowane po ustawieniu wartości null lub wartości domyślnej.

System.Text.Json Program udostępnia następujące sposoby ignorowania właściwości lub pól podczas serializacji:

Ponadto w programie .NET 7 i nowszych wersjach można dostosować kontrakt JSON tak, aby ignorował właściwości na podstawie dowolnych kryteriów. Aby uzyskać więcej informacji, zobacz Kontrakty niestandardowe.

System.Text.Json Program .NET Core 3.1 oferuje następujące sposoby ignorowania właściwości podczas serializacji:

Te opcje nie umożliwiają ignorowania wybranych właściwości na podstawie dowolnych kryteriów ocenianych w czasie wykonywania.

Ponadto w programie .NET Core 3.1 nie można:

  • Ignoruj wszystkie właściwości, które mają wartość domyślną dla typu.
  • Ignoruj wybrane właściwości, które mają wartość domyślną dla typu.
  • Ignoruj wybrane właściwości, jeśli ich wartość ma wartość null.
  • Ignoruj wybrane właściwości na podstawie dowolnych kryteriów ocenianych w czasie wykonywania.

W przypadku tej funkcji można napisać konwerter niestandardowy. Oto przykładowy kod POCO i niestandardowy konwerter dla niego, który ilustruje to podejście:

public class WeatherForecast
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
}
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 Summary pominięcie właściwości z serializacji, jeśli jej wartość ma wartość null, pusty ciąg lub "N/A".

Zarejestruj ten konwerter niestandardowy przy użyciu atrybutu w klasie lub przez dodanie konwerteraConverters do kolekcji.

Takie podejście wymaga dodatkowej logiki, jeśli:

  • Obiekt POCO zawiera złożone właściwości.
  • Musisz obsługiwać atrybuty, takie jak [JsonIgnore] lub opcje, takie jak kodery niestandardowe.

Pola publiczne i inne niż publiczne

Newtonsoft.Json może serializować i deserializować pola, a także właściwości.

W System.Text.Jsonsystemie użyj ustawienia globalnego JsonSerializerOptions.IncludeFields lub atrybutu [JsonInclude], aby uwzględnić pola publiczne podczas serializacji lub deserializacji. Aby zapoznać się z przykładem, zobacz Dołączanie pól.

System.Text.Json Program .NET Core 3.1 działa tylko z właściwościami publicznymi. Konwertery niestandardowe mogą zapewnić tę funkcję.

Zachowywanie odwołań do obiektów i pętle obsługi

Domyślnie Newtonsoft.Json serializuje według wartości. Jeśli na przykład obiekt zawiera dwie właściwości, które zawierają odwołanie do tego samego Person obiektu, wartości właściwości tego Person obiektu są zduplikowane w formacie JSON.

Newtonsoft.JsonPreserveReferencesHandling ma ustawienie, które JsonSerializerSettings umożliwia serializację według odwołania:

  • Metadane identyfikatora są dodawane do kodu JSON utworzonego dla pierwszego Person obiektu.
  • Kod JSON utworzony dla drugiego Person obiektu zawiera odwołanie do tego identyfikatora zamiast wartości właściwości.

Newtonsoft.Json Ma ReferenceLoopHandling również ustawienie, które pozwala ignorować odwołania cykliczne, a nie zgłaszać wyjątku.

Aby zachować odwołania i obsłużyć odwołania cykliczne w System.Text.Jsonelemencie , ustaw wartość JsonSerializerOptions.ReferenceHandlerPreserve. To ustawienie jest równoważne w elemencie ReferenceHandler.PreserveNewtonsoft.JsonPreserveReferencesHandling = PreserveReferencesHandling.All .

Opcja ReferenceHandler.IgnoreCycles ma zachowanie podobne do Newtonsoft.JsonReferenceLoopHandling.Ignore. Jedną z różnic jest to, że implementacja System.Text.Json zastępuje pętle odwołania tokenem null JSON zamiast ignorować odwołanie do obiektu. Aby uzyskać więcej informacji, zobacz Ignoruj odwołania cykliczne.

Podobnie jak w przypadku Newtonsoft.Jsonklasy ReferenceResolver, System.Text.Json.Serialization.ReferenceResolver klasa definiuje zachowanie zachowania odwołań do serializacji i deserializacji. Utwórz klasę pochodną, aby określić zachowanie niestandardowe. Aby zapoznać się z przykładem, zobacz GuidReferenceResolver.

Niektóre powiązane Newtonsoft.Json funkcje nie są obsługiwane:

System.Text.Json Program .NET Core 3.1 obsługuje tylko serializacji według wartości i zgłasza wyjątek dla odwołań cyklizowanych.

Słownik z kluczem niebędącym ciągiem

Zarówno Newtonsoft.Json , jak i System.Text.Json obsługują kolekcje typu Dictionary<TKey, TValue>. Jednak w systemie System.Text.JsonTKey musi być typem pierwotnym, a nie typem niestandardowym. Aby uzyskać więcej informacji, zobacz Obsługiwane typy kluczy.

Przestroga

Deserializowanie do Dictionary<TKey, TValue> lokalizacji, w której TKey jest wpisywane jako coś innego niż string może spowodować wprowadzenie luki w zabezpieczeniach w aplikacji zużywanej. Aby uzyskać więcej informacji, zobacz dotnet/runtime#4761.

Newtonsoft.Json obsługuje kolekcje typu Dictionary<TKey, TValue>. Wbudowana obsługa kolekcji słowników w System.Text.Json programie .NET Core 3.1 jest ograniczona do Dictionary<string, TValue>. Oznacza to, że klucz musi być ciągiem.

Aby obsługiwać słownik z liczbą całkowitą lub inny typ jako klucz w programie .NET Core 3.1, utwórz konwerter podobny do przykładu w temacie How to write custom converters (Jak pisać konwertery niestandardowe).

Typy bez wbudowanej obsługi

System.Text.Json Nie zapewnia wbudowanej obsługi następujących typów:

Konwertery niestandardowe można zaimplementować dla typów, które nie mają wbudowanej obsługi.

Serializacja polimorficzna

Newtonsoft.Json program automatycznie wykonuje serializacji polimorficznej. Począwszy od platformy .NET 7, System.Text.Json obsługuje serializacji polimorficznej za pomocą atrybutu JsonDerivedTypeAttribute . Aby uzyskać więcej informacji, zobacz Serializowanie właściwości klas pochodnych.

Deserializacja polimorficzna

Newtonsoft.JsonTypeNameHandling Ma ustawienie, które dodaje metadane nazwy typu do formatu JSON podczas serializacji. Używa metadanych podczas deserializacji do deserializacji polimorficznej. Począwszy od platformy .NET 7, System.Text.Json opiera się na dyskryminujących informacjach o typie w celu przeprowadzenia deserializacji polimorficznej. Te metadane są emitowane w formacie JSON, a następnie używane podczas deserializacji w celu określenia, czy deserializować typ podstawowy, czy typ pochodny. Aby uzyskać więcej informacji, zobacz Serializowanie właściwości klas pochodnych.

Aby obsługiwać deserializacji polimorficzne w starszych wersjach platformy .NET, utwórz konwerter podobny do przykładu w temacie How to write custom converters (Jak pisać niestandardowe konwertery).

Deserializacja właściwości obiektu

Gdy Newtonsoft.Json deserializuje do Object, to:

  • Wywnioskuje typ wartości pierwotnych w ładunku JSON (innym niż null) i zwraca przechowywany stringobiekt , , longdouble, booleanlub DateTime jako obiekt skrzynkowy. Wartości pierwotne to pojedyncze wartości JSON, takie jak liczba JSON, ciąg, true, falselub null.
  • JObject Zwraca wartość lub JArray dla wartości złożonych w ładunku JSON. Wartości złożone to kolekcje par klucz-wartość JSON w nawiasach klamrowych ({}) lub listach wartości w nawiasach kwadratowych ([]). Właściwości i wartości w nawiasach klamrowych lub nawiasach mogą mieć dodatkowe właściwości lub wartości.
  • Zwraca odwołanie o wartości null, gdy ładunek ma null literał JSON.

System.Text.Json przechowuje pola JsonElement zarówno dla wartości pierwotnych, jak i złożonych przy każdym deserializacji do Object, na przykład:

  • Właściwość object .
  • Wartość słownika object .
  • object Wartość tablicy.
  • Katalog główny object.

Jednak traktuje null to samo, co Newtonsoft.Json i zwraca odwołanie o wartości null, System.Text.Json gdy ładunek ma null literał JSON w nim.

Aby zaimplementować wnioskowanie typu dla object właściwości, utwórz konwerter podobny do przykładu w temacie How to write custom converters (Jak pisać konwertery niestandardowe).

Deserializowanie wartości null do typu niezerowego

Newtonsoft.Json Nie zgłasza wyjątku w następującym scenariuszu:

  • NullValueHandling jest ustawiona na Ignore, i
  • Podczas deserializacji kod JSON zawiera wartość null dla typu wartości innej niż null.

W tym samym scenariuszu System.Text.Json zgłaszany jest wyjątek. (Odpowiednie ustawienie obsługi wartości null w pliku System.Text.Json to JsonSerializerOptions.IgnoreNullValues = true.)

Jeśli jesteś właścicielem typu docelowego, najlepszym obejściem jest, aby właściwość, której dotyczy problem, ma wartość null (na przykład zmień wartość int na int?).

Innym obejściem jest utworzenie konwertera dla typu, takiego jak poniższy przykład, który obsługuje wartości null dla DateTimeOffset typów:

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

namespace SystemTextJsonSamples
{
    public class DateTimeOffsetNullHandlingConverter : JsonConverter<DateTimeOffset>
    {
        public override DateTimeOffset Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options) =>
            reader.TokenType == JsonTokenType.Null
                ? default
                : reader.GetDateTimeOffset();

        public override void Write(
            Utf8JsonWriter writer,
            DateTimeOffset dateTimeValue,
            JsonSerializerOptions options) =>
            writer.WriteStringValue(dateTimeValue);
    }
}

Zarejestruj ten konwerter niestandardowy przy użyciu atrybutu we właściwości lub przez dodanie konwerteraConverters do kolekcji.

Uwaga: Powyższy konwerter obsługuje wartości null inaczej niż Newtonsoft.Json w przypadku obiektów POC, które określają wartości domyślne. Załóżmy na przykład, że następujący kod reprezentuje obiekt docelowy:

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 powyższego konwertera:

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

Po deserializacji Date właściwość ma wartość 1/1/0001 (default(DateTimeOffset)), czyli wartość ustawioną w konstruktorze jest zastępowana. Biorąc pod uwagę ten sam kod POCO i JSON, Newtonsoft.Json deserializacja pozostawiłaby właściwość Date 1/1/2001.

Deserializowanie do niezmiennych klas i struktur

Newtonsoft.Json może deserializować do niezmiennych klas i struktur, ponieważ może używać konstruktorów, które mają parametry.

W System.Text.Jsonprogramie użyj atrybutu [JsonConstructor], aby określić użycie konstruktora sparametryzowanego. Rekordy w języku C# 9 są również niezmienne i są obsługiwane jako cele deserializacji. Aby uzyskać więcej informacji, zobacz Niezmienne typy i rekordy.

System.Text.Json w programie .NET Core 3.1 obsługuje tylko konstruktory bez parametrów publicznych. Aby obejść ten problem, można wywołać konstruktora z parametrami w konwerterze niestandardowym.

Oto niezmienna struktura z wieloma parametrami konstruktora:

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

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

Oto konwerter, który serializuje i deserializuje tę strukturę:

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) => 
            _intConverter = options?.GetConverter(typeof(int)) is JsonConverter<int> intConverter
                ? intConverter
                : 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;
            int? y = default;

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

            if (reader.ValueTextEquals(_xName.EncodedUtf8Bytes))
            {
                x = ReadProperty(ref reader, options);
            }
            else if (reader.ValueTextEquals(_yName.EncodedUtf8Bytes))
            {
                y = ReadProperty(ref reader, options);
            }
            else
            {
                throw new JsonException();
            }

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

            if (x.HasValue && reader.ValueTextEquals(_yName.EncodedUtf8Bytes))
            {
                y = ReadProperty(ref reader, options);
            }
            else if (y.HasValue && 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.GetValueOrDefault(), y.GetValueOrDefault());
        }

        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 Converters kolekcji.

Aby zapoznać się z przykładem podobnego konwertera obsługującego otwarte właściwości ogólne, zobacz wbudowany konwerter par klucz-wartość.

Wymagane właściwości

W Newtonsoft.Jsonpliku należy określić, że właściwość jest wymagana przez ustawienie Required atrybutu [JsonProperty] . Newtonsoft.Json zgłasza wyjątek, jeśli żadna wartość nie zostanie odebrana w formacie JSON dla właściwości oznaczonej jako wymagana.

Począwszy od platformy .NET 7, można użyć modyfikatora języka C# required lub atrybutu JsonRequiredAttribute wymaganej właściwości. System.Text.Json zgłasza wyjątek, jeśli ładunek JSON nie zawiera wartości dla oznaczonej właściwości. Aby uzyskać więcej informacji, zobacz Wymagane właściwości.

System.Text.Json nie zgłasza wyjątku, jeśli żadna wartość nie zostanie odebrana dla jednej z właściwości typu docelowego. Jeśli na przykład masz klasę WeatherForecast :

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:

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

Aby deserializacja nie powiodła się, jeśli żadna właściwość nie Date znajduje się w formacie JSON, wybierz jedną z następujących opcji:

Poniższy przykładowy kod konwertera zgłasza wyjątek, jeśli Date właściwość nie jest ustawiona po zakończeniu deserializacji:

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
            return forecast!.Date == default
                ? throw new JsonException("Required property not received in the JSON")
                : forecast;
        }

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

Zarejestruj ten konwerter niestandardowy, dodając konwerter do JsonSerializerOptions.Converters kolekcji.

Ten wzorzec rekursywnie wywołujący konwerter wymaga zarejestrowania konwertera przy użyciu metody , a nie przy JsonSerializerOptionsużyciu atrybutu . W przypadku zarejestrowania konwertera przy użyciu atrybutu konwerter niestandardowy rekursywnie wywołuje się w sobie. Wynikiem jest nieskończona pętla, która kończy się wyjątkiem przepełnienia stosu.

Podczas rejestrowania konwertera przy użyciu obiektu options należy unikać nieskończonej pętli, nie przekazując obiektu options podczas cyklicznego wywoływania Serialize lub Deserialize. Obiekt options zawiera Converters kolekcję. Jeśli przekazujesz go do Serialize lub Deserialize, niestandardowy konwerter wywołuje się do siebie, tworząc nieskończoną pętlę, która powoduje wyjątek przepełnienia stosu. Jeśli opcje domyślne nie są możliwe, utwórz nowe wystąpienie opcji z potrzebnymi ustawieniami. Takie podejście będzie powolne, ponieważ każde nowe wystąpienie buforuje się niezależnie.

Istnieje alternatywny wzorzec, który może używać JsonConverterAttribute rejestracji w klasie do przekonwertowania. W tym podejściu kod konwertera wywołuje Serialize lub Deserialize klasę, która pochodzi z klasy, która ma zostać przekonwertowana. Klasa pochodna nie ma JsonConverterAttribute do niej zastosowania. W poniższym przykładzie tej alternatywy:

  • WeatherForecastWithRequiredPropertyConverterAttribute jest klasą, która ma być deserializowana i ma JsonConverterAttribute do niej zastosowanie.
  • WeatherForecastWithoutRequiredPropertyConverterAttribute jest klasą pochodną, która nie ma atrybutu konwertera.
  • Kod w wywołaniach Serialize konwertera i Deserialize na, WeatherForecastWithoutRequiredPropertyConverterAttribute aby uniknąć nieskończonej pętli. Istnieje koszt wydajności dla tej metody serializacji z powodu dodatkowego wystąpienia obiektu i kopiowania wartości właściwości.

Oto WeatherForecast* typy:

[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
{
}

A oto konwerter:

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.
            return forecast!.Date == default
                ? throw new JsonException("Required property not received in the JSON")
                : 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);
        }
    }
}

Wymagany konwerter właściwości wymaga dodatkowej logiki, jeśli musisz obsługiwać atrybuty, takie jak [JsonIgnore] lub różne opcje, takie jak kodery niestandardowe. Ponadto przykładowy kod nie obsługuje właściwości, dla których wartość domyślna jest ustawiana w konstruktorze. Takie podejście nie rozróżnia następujących scenariuszy:

  • Brak właściwości w formacie JSON.
  • Właściwość typu bez wartości null jest obecna w formacie JSON, ale wartość jest wartością domyślną dla typu, takiego jak zero dla elementu int.
  • Właściwość typu wartości dopuszczalnej do wartości null jest obecna w formacie JSON, ale wartość ma wartość null.

Uwaga

Jeśli używasz z System.Text.Json kontrolera ASP.NET Core, możesz użyć [Required] atrybutu we właściwościach klasy modelu zamiast implementowania konwerteraSystem.Text.Json.

Określanie formatu daty

Newtonsoft.Json Udostępnia kilka sposobów kontrolowania DateTime , w jaki sposób właściwości i DateTimeOffset typy są serializowane i deserializowane:

  • Ustawienie DateTimeZoneHandling może służyć do serializacji wszystkich DateTime wartości jako daty UTC.
  • Ustawienia DateFormatString i DateTime konwertery mogą służyć do dostosowywania formatu ciągów dat.

System.Text.Json obsługuje standard ISO 8601-1:2019, w tym profil RFC 3339. Ten format jest powszechnie przyjęty, jednoznaczny i sprawia, że zaokrąglone podróże precyzyjnie. Aby użyć dowolnego innego formatu, utwórz konwerter niestandardowy. Na przykład następujące konwertery serializują i deserializują kod JSON, który używa formatu epoki Unix z przesunięciem strefy czasowej lub bez jej przesunięcia (wartości, takie jak /Date(1590863400000-0700)/ lub /Date(1590863400000)/):

sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
    static readonly DateTimeOffset s_epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
    static readonly Regex s_regex = new Regex("^/Date\\(([+-]*\\d+)([+-])(\\d{2})(\\d{2})\\)/$", RegexOptions.CultureInvariant);

    public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {

        string formatted = reader.GetString()!;
        Match match = s_regex.Match(formatted);

        if (
                !match.Success
                || !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
                || !int.TryParse(match.Groups[3].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
                || !int.TryParse(match.Groups[4].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
        {
            throw new JsonException();
        }

        int sign = match.Groups[2].Value[0] == '+' ? 1 : -1;
        TimeSpan utcOffset = new TimeSpan(hours * sign, minutes * sign, 0);

        return s_epoch.AddMilliseconds(unixTime).ToOffset(utcOffset);
    }

    public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
    {
        long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
        TimeSpan utcOffset = value.Offset;

        string formatted = FormattableString.Invariant($"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");
        writer.WriteStringValue(formatted);
    }
}
sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
{
    static readonly DateTime s_epoch = new DateTime(1970, 1, 1, 0, 0, 0);
    static readonly Regex s_regex = new Regex("^/Date\\(([+-]*\\d+)\\)/$", RegexOptions.CultureInvariant);

    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {

        string formatted = reader.GetString()!;
        Match match = s_regex.Match(formatted);

        if (
                !match.Success
                || !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime))
        {
            throw new JsonException();
        }

        return s_epoch.AddMilliseconds(unixTime);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);

        string formatted = FormattableString.Invariant($"/Date({unixTime})/");
        writer.WriteStringValue(formatted);
    }
}

Aby uzyskać więcej informacji, zobacz Obsługa typu DateTime i DateTimeOffset w systemie System.Text.Json.

Wywołania zwrotne

Newtonsoft.Json umożliwia wykonywanie kodu niestandardowego w kilku punktach w procesie serializacji lub deserializacji:

  • OnDeserializing (gdy zaczyna się deserializować obiekt)
  • OnDeserialized (po zakończeniu deserializacji obiektu)
  • OnSerializing (po rozpoczęciu serializacji obiektu)
  • OnSerialized (po zakończeniu serializacji obiektu)

System.Text.Json uwidacznia te same powiadomienia podczas serializacji i deserializacji. Aby ich używać, zaimplementuj co najmniej jeden z następujących interfejsów z System.Text.Json.Serialization przestrzeni nazw:

Oto przykład, który sprawdza właściwość null i zapisuje komunikaty na początku i na końcu serializacji i deserializacji:

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

namespace Callbacks
{
    public class WeatherForecast : 
        IJsonOnDeserializing, IJsonOnDeserialized, 
        IJsonOnSerializing, IJsonOnSerialized
    {
        public DateTime Date { get; set; }
        public int TemperatureCelsius { get; set; }
        public string? Summary { get; set; }

        void IJsonOnDeserializing.OnDeserializing() => Console.WriteLine("\nBegin deserializing");
        void IJsonOnDeserialized.OnDeserialized()
        {
            Validate();
            Console.WriteLine("Finished deserializing");
        }
        void IJsonOnSerializing.OnSerializing()
        {
            Console.WriteLine("Begin serializing");
            Validate();
        }
        void IJsonOnSerialized.OnSerialized() => Console.WriteLine("Finished serializing");

        private void Validate()
        {
            if (Summary is null)
            {
                Console.WriteLine("The 'Summary' property is 'null'.");
            }
        }
    }

    public class Program
    {
        public static void Main()
        {
            var weatherForecast = new WeatherForecast
            {
                Date = DateTime.Parse("2019-08-01"),
                TemperatureCelsius = 25,
            };

            string jsonString = JsonSerializer.Serialize(weatherForecast);
            Console.WriteLine(jsonString);

            weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(jsonString);
            Console.WriteLine($"Date={weatherForecast?.Date}");
            Console.WriteLine($"TemperatureCelsius={weatherForecast?.TemperatureCelsius}");
            Console.WriteLine($"Summary={weatherForecast?.Summary}");
        }
    }
}
// output:
//Begin serializing
//The 'Summary' property is 'null'.
//Finished serializing
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":null}

//Begin deserializing
//The 'Summary' property is 'null'.
//Finished deserializing
//Date=8/1/2019 12:00:00 AM
//TemperatureCelsius = 25
//Summary=

Kod OnDeserializing nie ma dostępu do nowego wystąpienia POCO. Aby manipulować nowym wystąpieniem POCO na początku deserializacji, umieść ten kod w konstruktorze POCO.

W System.Text.Jsonprogramie można symulować wywołania zwrotne, pisząc konwerter niestandardowy. W poniższym przykładzie przedstawiono niestandardowy konwerter dla funkcji POCO. Konwerter zawiera kod, który wyświetla komunikat w każdym punkcie odpowiadający wywołaniu zwrotnemu Newtonsoft.Json .

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");
        }
    }
}

Zarejestruj ten konwerter niestandardowy, dodając konwerter do Converters kolekcji.

Jeśli używasz konwertera niestandardowego, który jest zgodny z poprzednim przykładem:

  • Kod OnDeserializing nie ma dostępu do nowego wystąpienia POCO. Aby manipulować nowym wystąpieniem POCO na początku deserializacji, umieść ten kod w konstruktorze POCO.
  • Unikaj nieskończonej pętli, rejestrując konwerter w obiekcie options i nie przekazując obiektu options w przypadku cyklicznego wywoływania Serialize lub Deserialize.

Aby uzyskać więcej informacji na temat konwerterów niestandardowych, które rekursywnie wywołają Serialize metodę lub Deserialize, zobacz sekcję Wymagane właściwości we wcześniejszej części tego artykułu.

Zestawy właściwości innych niż publiczne i getters

Newtonsoft.Json może używać prywatnych i wewnętrznych zestawów właściwości i getters za pośrednictwem atrybutu JsonProperty .

System.Text.Jsonobsługuje zestawy właściwości prywatnych i wewnętrznych i getters za pośrednictwem atrybutu [JsonInclude]. Aby uzyskać przykładowy kod, zobacz Metody dostępu do właściwości innych niż publiczne.

System.Text.Json w programie .NET Core 3.1 obsługuje tylko publiczne zestawy. Konwertery niestandardowe mogą zapewnić tę funkcję.

Wypełnianie istniejących obiektów

Metoda JsonConvert.PopulateObject w Newtonsoft.Json deserializuje dokument JSON do istniejącego wystąpienia klasy, zamiast tworzyć nowe wystąpienie. System.Text.Json zawsze tworzy nowe wystąpienie typu docelowego przy użyciu domyślnego konstruktora bez parametrów publicznych. Konwertery niestandardowe mogą deserializacji do istniejącego wystąpienia.

Ponowne używanie, a nie zastępowanie właściwości

Ustawienie Newtonsoft.JsonObjectCreationHandling umożliwia określenie, że obiekty we właściwościach powinny być ponownie używane, a nie zastępowane podczas deserializacji. System.Text.Json zawsze zastępuje obiekty we właściwościach. Konwertery niestandardowe mogą zapewnić tę funkcję.

Dodawanie do kolekcji bez zestawów

Podczas deserializacji dodaje obiekty do kolekcji, Newtonsoft.Json nawet jeśli właściwość nie ma ustawiacza. System.Text.Json ignoruje właściwości, które nie mają zestawów. Konwertery niestandardowe mogą zapewnić tę funkcję.

Zasady nazewnictwa liter węża

Jedyną wbudowaną zasadą nazewnictwa właściwości jest System.Text.Jsonprzypadek camel. Newtonsoft.Json może konwertować nazwy właściwości na przypadek węża. Niestandardowe zasady nazewnictwa mogą zapewnić tę funkcję. Aby uzyskać więcej informacji, zobacz problem z usługą GitHub dotnet/runtime #782.

Atrybuty System.Runtime.Serialization

System.Text.Json nie obsługuje atrybutów z System.Runtime.Serialization przestrzeni nazw, takich jak DataMemberAttribute i IgnoreDataMemberAttribute.

Liczby ósemkowe

Newtonsoft.Json traktuje liczby z zerem wiodącym jako liczby ósemkowe. System.Text.Json nie zezwala na zera wiodące, ponieważ specyfikacja RFC 8259 nie zezwala na nie.

MissingMemberHandling

Newtonsoft.Json można skonfigurować tak, aby zgłaszać wyjątki podczas deserializacji, jeśli kod JSON zawiera właściwości, których brakuje w typie docelowym. System.Text.Jsonignoruje dodatkowe właściwości w formacie JSON, z wyjątkiem użycia atrybutu [JsonExtensionData]. Brak obejścia brakującej funkcji elementu członkowskiego.

TraceWriter

Newtonsoft.Json umożliwia debugowanie przy użyciu elementu do TraceWriter wyświetlania dzienników generowanych przez serializacji lub deserializacji. System.Text.Json nie wykonuje rejestrowania.

JsonDocument i JsonElement w porównaniu do JToken (na przykład JObject, JArray)

System.Text.Json.JsonDocument Zapewnia możliwość analizowania i tworzenia modelu obiektów dokumentów tylko do odczytu (DOM) z istniejących ładunków JSON. Dom zapewnia losowy dostęp do danych w ładunku JSON. Dostęp do elementów JSON, które tworzą ładunek, można uzyskać za pośrednictwem JsonElement typu. Typ JsonElement udostępnia interfejsy API do konwertowania tekstu JSON na typowe typy platformy .NET. JsonDocument uwidacznia RootElement właściwość.

Począwszy od platformy .NET 6, można przeanalizować i utworzyć modyfikowalny dom z istniejących ładunków JSON przy użyciu JsonNode typu i innych typów w System.Text.Json.Nodes przestrzeni nazw. Aby uzyskać więcej informacji, zobacz Use JsonNode.

JsonDocument to IDisposable

JsonDocument tworzy widok danych w pamięci do buforu w puli. W związku z tym, w przeciwieństwie do JObject lub JArray z Newtonsoft.Json, JsonDocument typ implementuje IDisposable i musi być używany wewnątrz bloku przy użyciu. Aby uzyskać więcej informacji, zobacz JsonDocument is IDisposable.

Dokument JsonDocument jest tylko do odczytu

Dom System.Text.Json nie może dodawać, usuwać ani modyfikować elementów JSON. Jest ona zaprojektowana w ten sposób pod kątem wydajności i zmniejszenia alokacji na potrzeby analizowania typowych rozmiarów ładunków JSON (czyli < 1 MB).

Jeśli w twoim scenariuszu obecnie jest używany modyfikowalny dom, można wykonać jedno z następujących obejść:

  • Aby utworzyć JsonDocument od podstaw (czyli bez przekazywania istniejącego ładunku JSON do Parse metody), napisz tekst JSON przy użyciu Utf8JsonWriter i przeanalizuj dane wyjściowe z tego, aby utworzyć nowy JsonDocument.
  • Aby zmodyfikować istniejący JsonDocumentelement , użyj go do pisania tekstu JSON, wprowadzania zmian podczas pisania i analizowania danych wyjściowych z niego w celu wprowadzenia nowego JsonDocumentpliku .
  • Aby scalić istniejące dokumenty JSON, równoważne interfejsom JObject.Merge API lub JContainer.Merge z usługi , zobacz ten problem z Newtonsoft.Jsonusługą GitHub.

Te obejścia są niezbędne tylko w przypadku wersji System.Text.Json starszych niż 6.0. W wersji 6.0 można użyć narzędzia JsonNode do pracy z modyfikowalnym modelem DOM.

JsonElement to struktura unii

JsonDocument uwidacznia RootElement jako właściwość typu JsonElement, która jest typem struktury unii, który obejmuje dowolny element JSON. Newtonsoft.Json używa dedykowanych typów hierarchicznych, takich jak JObject,JArray, JTokeni tak dalej. JsonElement jest to, co można wyszukiwać i wyliczać, i można użyć JsonElement do materializowania elementów JSON w typach platformy .NET.

Począwszy od platformy .NET 6, można użyć JsonNode typów i typów w przestrzeni nazw odpowiadającej System.Text.Json.NodesJObjectelementom ,JArray i JToken. Aby uzyskać więcej informacji, zobacz Use JsonNode.

Jak wyszukiwać elementy podrzędne JsonDocument i JsonElement

Wyszukuje tokeny JSON przy użyciu JObject lub JArray zazwyczaj Newtonsoft.Json są stosunkowo szybkie, ponieważ są one wyszukiwane w pewnym słowniku. W porównaniu wyszukiwania wymagają JsonElement sekwencyjnego wyszukiwania właściwości i dlatego są stosunkowo powolne (na przykład w przypadku używania metody TryGetProperty). System.Text.Json jest przeznaczony do zminimalizowania czasu analizy początkowej, a nie czasu wyszukiwania. Aby uzyskać więcej informacji, zobacz How to search a JsonDocument and JsonElement for sub-elements (Jak wyszukać element podrzędny JsonDocument i JsonElement).

Utf8JsonReader w porównaniu do elementu JsonTextReader

System.Text.Json.Utf8JsonReaderto wysokowydajny, niski przydział, czytnik tylko do przodu dla zakodowanego w formacie UTF-8 tekstu JSON, odczytywany z bajtu> ReadOnlySpan< lub bajtu ReadOnlySequence<>. Jest Utf8JsonReader to typ niskiego poziomu, który może służyć do tworzenia niestandardowych parserów i deserializatorów.

Utf8JsonReader to struktura ref

Element JsonTextReader in Newtonsoft.Json jest klasą. Typ Utf8JsonReader różni się w tym, że jest to struktura ref. Aby uzyskać więcej informacji, zobacz Utf8JsonReader to struktura ref.

Odczytywanie wartości null do typów wartości dopuszczalnych do wartości null

Newtonsoft.Json Udostępnia interfejsy API zwracające Nullable<T>element , takie jak ReadAsBoolean, który obsługuje NullTokenType element za Ciebie, zwracając element bool?. Wbudowane System.Text.Json interfejsy API zwracają tylko typy wartości innych niż null. Aby uzyskać więcej informacji, zobacz Odczyt wartości null do typów wartości dopuszczalnych do wartości null.

Obsługa wielu elementów docelowych

Jeśli musisz nadal używać Newtonsoft.Json dla niektórych platform docelowych, możesz mieć wiele implementacji i mieć dwie implementacje. Nie jest to jednak proste i wymagałoby to duplikowania niektórych #ifdefs i źródeł. Jednym ze sposobów udostępniania jak największej ref struct ilości kodu jest utworzenie otoki wokół Utf8JsonReader i Newtonsoft.JsonJsonTextReader. Ta otoka ujmuje obszar powierzchni publicznej, a jednocześnie izoluje różnice behawioralne. Dzięki temu można odizolować zmiany głównie do konstrukcji typu wraz z przekazaniem nowego typu według odwołania. Jest to wzorzec, który jest zgodny z biblioteką Microsoft.Extensions.DependencyModel :

Utf8JsonWriter w porównaniu do JsonTextWriter

System.Text.Json.Utf8JsonWriter Jest to wysokowydajny sposób zapisu zakodowanego w formacie UTF-8 tekstu JSON z typowych typów platformy .NET, takich jak String, Int32i DateTime. Składnik zapisywania to typ niskiego poziomu, który może służyć do tworzenia niestandardowych serializatorów.

Zapisywanie wartości pierwotnych

Metoda Newtonsoft.JsonWriteRawValue zapisuje nieprzetworzone dane JSON, gdzie oczekiwano wartości. System.Text.Json ma bezpośredni odpowiednik: Utf8JsonWriter.WriteRawValue. Aby uzyskać więcej informacji, zobacz Zapisywanie nieprzetworzonego kodu JSON.

Metoda Newtonsoft.JsonWriteRawValue zapisuje nieprzetworzone dane JSON, gdzie oczekiwano wartości. Istnieje równoważna metoda , Utf8JsonWriter.WriteRawValuew programie .NET 6 i nowszych wersjach. Aby uzyskać więcej informacji, zobacz Zapisywanie nieprzetworzonego kodu JSON.

W przypadku wersji starszych niż 6.0 System.Text.Json nie ma równoważnej metody pisania nieprzetworzonego kodu JSON. Jednak następujące obejście zapewnia, że tylko prawidłowy kod JSON jest zapisywany:

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

Dostosowywanie formatu JSON

JsonTextWriter zawiera następujące ustawienia, dla których Utf8JsonWriter nie ma odpowiednika:

  • Wcięcie — określa liczbę znaków do wcięcia. Utf8JsonWriter zawsze wcięcie o 2 znaki.
  • IndentChar — określa znak, który ma być używany do wcięcia. Utf8JsonWriter zawsze używa białych znaków.
  • QuoteChar — określa znak, który ma być używany do otaczania wartości ciągów. Utf8JsonWriter zawsze używa cudzysłowów podwójnych.
  • QuoteName — określa, czy należy otaczać nazwy właściwości cudzysłowami. Utf8JsonWriter zawsze otacza je cudzysłowami.

Nie ma obejść, które umożliwiają dostosowanie kodu JSON utworzonego Utf8JsonWriter w ten sposób.

Zapisywanie wartości przedziału czasu, identyfikatora URI lub znaku

JsonTextWriter Udostępnia WriteValue metody wartości TimeSpan, Uri i char . Utf8JsonWriter nie ma równoważnych metod. Zamiast tego sformatuj te wartości jako ciągi (na przykład przez wywołanie ToString()metody , ) i wywołaj metodę WriteStringValue.

Obsługa wielu elementów docelowych

Jeśli musisz nadal używać Newtonsoft.Json dla niektórych platform docelowych, możesz mieć wiele implementacji i mieć dwie implementacje. Nie jest to jednak proste i wymagałoby to duplikowania niektórych #ifdefs i źródeł. Jednym ze sposobów udostępniania jak największej ilości kodu jest utworzenie otoki wokół Utf8JsonWriter i NewtonsoftJsonTextWriter. Ta otoka ujmuje obszar powierzchni publicznej, a jednocześnie izoluje różnice behawioralne. Pozwala to odizolować zmiany głównie do konstrukcji typu. Biblioteka Microsoft.Extensions.DependencyModel jest następująca:

TypeNameHandling.All nie jest obsługiwany

Decyzja o wykluczeniu TypeNameHandling.Allfunkcji równoważnych z System.Text.Json tych funkcji była celowa. Umożliwianie ładunku JSON w celu określenia własnych informacji o typie jest typowym źródłem luk w zabezpieczeniach w aplikacjach internetowych. W szczególności konfigurowanie Newtonsoft.Json za TypeNameHandling.All pomocą polecenia umożliwia klientowi zdalnemu osadzanie całej aplikacji wykonywalnego w samym ładunku JSON, dzięki czemu podczas deserializacji aplikacja internetowa wyodrębnia i uruchamia osadzony kod. Aby uzyskać więcej informacji, zobacz piątek 13. ataków JSON w programie PowerPoint i piątek szczegóły ataków JSON 13.

Kwerendy ścieżki JSON nie są obsługiwane

Dom JsonDocument nie obsługuje wykonywania zapytań przy użyciu ścieżki JSON.

W modelu JsonNode DOM każde JsonNode wystąpienie ma metodę zwracającą GetPath ścieżkę do tego węzła. Nie ma jednak wbudowanego interfejsu API do obsługi zapytań opartych na ciągach zapytania ścieżki JSON.

Aby uzyskać więcej informacji, zobacz problem z usługą GitHub dotnet/runtime #31068.

Niektóre limity nie można skonfigurować

System.Text.Json ustawia limity, których nie można zmienić dla niektórych wartości, takich jak maksymalny rozmiar tokenu w znakach (166 MB) i podstawowe 64 (125 MB). Aby uzyskać więcej informacji, zobacz JsonConstants w kodzie źródłowym i problemie z usługą GitHub dotnet/runtime #39953.

NaN, Infinity, -Infinity

Newtonsoft analizuje tokeny NaNciągów , Infinityi -Infinity JSON. W programie .NET Core 3.1 nie obsługuje tych tokenów, System.Text.Json ale możesz napisać niestandardowy konwerter do obsługi tych tokenów. W programie .NET 5 i nowszych wersjach użyj polecenia JsonNumberHandling.AllowNamedFloatingPointLiterals. Aby uzyskać informacje o sposobie korzystania z tego ustawienia, zobacz Zezwalaj lub zapisuj liczby w cudzysłowie.

Dodatkowe zasoby