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 tychNewtonsoft.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 |
Required ustawienie 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 |
Required ustawienie 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 |
Required ustawienie atrybutu [JsonProperty] |
⚠️ Nieobsługiwane, obejście, przykład |
NullValueHandling ustawienie atrybutu [JsonProperty] |
⚠️ Nieobsługiwane, obejście, przykład |
DefaultValueHandling ustawienie 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.Json
ma 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
iDefaultValueHandling
JsonSerializerSettings
umożliwiają określenie, że wszystkie właściwości null-value lub default-value powinny być ignorowane. - Ustawienia
NullValueHandling
iDefaultValueHandling
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:
- Atrybut [JsonIgnore] we właściwości powoduje pominięcie właściwości z formatu JSON podczas serializacji.
- Opcja globalna IgnoreReadOnlyProperties umożliwia ignorowanie wszystkich właściwości tylko do odczytu.
- Jeśli dołączasz pola, JsonSerializerOptions.IgnoreReadOnlyFields opcja globalna umożliwia ignorowanie wszystkich pól tylko do odczytu.
- Opcja
DefaultIgnoreCondition
globalna umożliwia ignorowanie wszystkich właściwości typu wartości, które mają wartości domyślne, lub ignorowanie wszystkich właściwości typu odwołania, które mają wartości null.
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:
- Atrybut [JsonIgnore] we właściwości powoduje pominięcie właściwości z formatu JSON podczas serializacji.
- Opcja globalna IgnoreNullValues umożliwia ignorowanie wszystkich właściwości null-value.
IgnoreNullValues
jest przestarzała na platformie .NET 5 i nowszych wersjach, więc nie jest wyświetlana przez funkcję IntelliSense. Aby zapoznać się z bieżącym sposobem ignorowania wartości null, zobacz , jak ignorować wszystkie właściwości null-value na platformie .NET 5 i nowszych wersjach. - Opcja globalna IgnoreReadOnlyProperties umożliwia ignorowanie wszystkich właściwości tylko do odczytu.
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.Json
PreserveReferencesHandling
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.Preserve
Newtonsoft.Json
PreserveReferencesHandling
= 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:
Aby uzyskać więcej informacji, zobacz Zachowywanie odwołań i obsługa odwołań cykli.
- JsonPropertyAttribute.IsReference
- JsonPropertyAttribute.ReferenceLoopHandling
- JsonSerializerSettings.ReferenceLoopHandling
Aby uzyskać więcej informacji, zobacz Zachowywanie odwołań i obsługa odwołań cykli.
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.Json
TKey
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:
- DataTable i powiązane typy (aby uzyskać więcej informacji, zobacz Obsługiwane typy kolekcji)
- Typy języka F#, takie jak dyskryminowane związki zawodowe. Typy rekordów i anonimowe typy rekordów są traktowane jako niezmienne obiekty weryfikacji koncepcji i dlatego są obsługiwane.
- TimeSpan
- Typy języka F#, takie jak dyskryminowane związki, typy rekordów i typy rekordów anonimowych.
- TimeSpan
- ExpandoObject
- TimeZoneInfo
- BigInteger
- DBNull
- Type
- ValueTuple i skojarzone z nimi typy ogólne
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.Json
TypeNameHandling
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 przechowywanystring
obiekt , ,long
double
,boolean
lubDateTime
jako obiekt skrzynkowy. Wartości pierwotne to pojedyncze wartości JSON, takie jak liczba JSON, ciąg,true
,false
lubnull
. JObject
Zwraca wartość lubJArray
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 naIgnore
, 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.Json
pliku 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:
- Użyj programu .NET 7 lub nowszej System.Text.Json wersji pakietu i dodaj
required
modyfikator (dostępny począwszy od języka C# 11) lub JsonRequiredAttribute atrybut do właściwości. - Zaimplementuj konwerter niestandardowy.
- Zaimplementuj
OnDeserialized
wywołanie zwrotne (.NET 6 i nowsze).
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 maJsonConverterAttribute
do niej zastosowanie.WeatherForecastWithoutRequiredPropertyConverterAttribute
jest klasą pochodną, która nie ma atrybutu konwertera.- Kod w wywołaniach
Serialize
konwertera iDeserialize
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 wszystkichDateTime
wartości jako daty UTC. - Ustawienia
DateFormatString
iDateTime
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
lubDeserialize
.
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.Json
ObjectCreationHandling
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 doParse
metody), napisz tekst JSON przy użyciuUtf8JsonWriter
i przeanalizuj dane wyjściowe z tego, aby utworzyć nowyJsonDocument
. - Aby zmodyfikować istniejący
JsonDocument
element , użyj go do pisania tekstu JSON, wprowadzania zmian podczas pisania i analizowania danych wyjściowych z niego w celu wprowadzenia nowegoJsonDocument
pliku . - Aby scalić istniejące dokumenty JSON, równoważne interfejsom
JObject.Merge
API lubJContainer.Merge
z usługi , zobacz ten problem zNewtonsoft.Json
usł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
, JToken
i 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.NodesJObject
elementom ,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 Null
TokenType
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.Json
JsonTextReader
. 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
, Int32
i 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.Json
WriteRawValue
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.Json
WriteRawValue
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 Newtonsoft
JsonTextWriter
. 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.All
funkcji 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 NaN
ciągów , Infinity
i -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
- System.Text.Json Przegląd
- Jak serializować i deserializować dane JSON
- Tworzenie wystąpienia wystąpień JsonSerializerOptions
- Włączanie dopasowywania bez uwzględniania wielkości liter
- Dostosowywanie nazw i wartości właściwości
- Ignorowanie właściwości
- Zezwalanie na nieprawidłowy kod JSON
- Obsługa przepełnienia kodu JSON lub JsonElement lub JsonNode
- Zachowywanie odwołań i obsługa odwołań cyklicznych
- Deserializacji do niezmiennych typów i niepublizowanych metod dostępu
- Serializacja polimorficzna
- Dostosowywanie kodowania znaków
- Używanie modelu DOM, Utf8JsonReader i Utf8JsonWriter
- Pisanie niestandardowych konwerterów na potrzeby serializacji JSON
- Obsługa elementu DateTime i DateTimeOffset
- Jak używać generowania źródła
- Obsługiwane typy kolekcji
- System.Text.Json Dokumentacja interfejsu API
- System.Text.Json. Dokumentacja interfejsu API serializacji