Sdílet prostřednictvím


Migrace z Newtonsoft.Json do System.Text.Json

Tento článek ukazuje, jak migrovat z Newtonsoft.Json do System.Text.Json.

Obor System.Text.Json názvů poskytuje funkce pro serializaci do a deserializaci z JavaScript Object Notation (JSON). Knihovna System.Text.Json je součástí modulu runtime pro .NET Core 3.1 a novější verze. V případě jiných cílových architektur nainstalujte System.Text.Json balíček NuGet. Balíček podporuje:

  • .NET Standard 2.0 a novější verze
  • .NET Framework 4.6.2 a novější verze
  • .NET Core 2.0, 2.1 a 2.2

Tip

Pomoc s AI můžete použít k migraci z Newtonsoft.Json GitHub Copilotu.

System.Text.Json zaměřuje se především na dodržování předpisů v oblasti výkonu, zabezpečení a standardů. Má několik klíčových rozdílů ve výchozím chování a nemá za cíl mít paritu funkcí s Newtonsoft.Json. V některých scénářích System.Text.Json aktuálně nemá žádné integrované funkce, ale existují doporučená alternativní řešení. V jiných scénářích jsou alternativní řešení nepraktická.

Tým System.Text.Json investuje do přidávání funkcí, které jsou nejčastěji požadovány. Pokud vaše aplikace závisí na chybějící funkci, zvažte vytvoření problému v úložišti GitHubu dotnet/runtime a zjistěte, jestli je možné přidat podporu pro váš scénář.

Většina tohoto článku se zabývá tím, jak používat JsonSerializer rozhraní API, ale obsahuje také pokyny k použití JsonDocument (které představuje objektový model dokumentu nebo MODEL DOM) Utf8JsonReadera Utf8JsonWriter typy.

V jazyce Visual Basic nemůžete použít Utf8JsonReader, což také znamená, že nemůžete psát vlastní převaděče. Většina zde uvedených alternativních řešení vyžaduje, abyste napsali vlastní převaděče. Vlastní převaděč můžete napsat v jazyce C# a zaregistrovat ho v projektu jazyka Visual Basic. Další informace naleznete v tématu Podpora jazyka Visual Basic.

Tabulka rozdílů

Následující tabulka uvádí Newtonsoft.Json funkce a System.Text.Json ekvivalenty. Ekvivalenty spadají do následujících kategorií:

  • ✔️ Podporováno integrovanými funkcemi. Získání podobného chování System.Text.Json může vyžadovat použití atributu nebo globální možnosti.
  • ⚠✔ Nepodporováno, ale alternativní řešení je možné. Alternativní řešení jsou vlastní převaděče, které nemusí poskytovat úplnou paritu s funkcemi Newtonsoft.Json . Pro některé z nich je ukázkový kód k dispozici jako příklady. Pokud se na tyto Newtonsoft.Json funkce spoléháte, migrace bude vyžadovat úpravy vašich objektů .NET nebo jiných změn kódu.
  • ❌ Nepodporuje se a alternativní řešení není praktické nebo možné. Pokud se na tyto Newtonsoft.Json funkce spoléháte, migrace nebude možná bez významných změn.
Funkce systému Newtonsoft.Json System.Text.Json ekvivalentní
Ve výchozím nastavení se nerozlišují malá a velká písmena ✔️ Globální nastavení PropertyNameCaseInsensitive
Názvy vlastností camel-case ✔️ Globální nastavení PropertyNamingPolicy
Názvy vlastností hadího případu ✔️ Zásady pojmenování hadího případu
Minimální znakové zapouzdření ✔️ Striktní zapouzdření znaků, konfigurovatelné
NullValueHandling.Ignore globální nastavení ✔️ Globální možnost DefaultIgnoreCondition
Povolit komentáře ✔️ Globální nastavení ReadCommentHandling
Povolit koncové čárky ✔️ Globální nastavení AllowTrailingCommas
Registrace vlastního převaděče ✔️ Pořadí priorit se liší
Výchozí maximální hloubka 64, konfigurovatelná ✔️ Výchozí maximální hloubka 64, konfigurovatelná
PreserveReferencesHandling globální nastavení ✔️ Globální nastavení ReferenceHandling
Serializace nebo deserializace čísel v uvozovkách ✔️ Globální nastavení NumberHandling, atribut [JsonNumberHandling]
Deserializace na neměnné třídy a struktury ✔️ JsonConstructor, C# 9 Records
Podpora polí ✔️ Globální nastavení IncludeFields, atribut [JsonInclude]
DefaultValueHandling globální nastavení ✔️ Globální nastavení DefaultIgnoreCondition
NullValueHandling nastavení zapnuto [JsonProperty] ✔️ Atribut JsonIgnore
DefaultValueHandling nastavení zapnuto [JsonProperty] ✔️ Atribut JsonIgnore
Deserializace Dictionary s klíčem bez řetězce ✔️ Podporovaný
Podpora neveřejných objektů setter a getters ✔️ Atribut JsonInclude
Atribut [JsonConstructor] ✔️ [JsonConstructor] – atribut
ReferenceLoopHandling globální nastavení ✔️ Globální nastavení ReferenceHandling
Zpětná volání ✔️ Zpětných volání
NaN, Nekonečno, -Nekonečno ✔️ Podporovaný
Requirednastavení atributu [JsonProperty] ✔️ Atribut [JsonRequired] a požadovaný modifikátor jazyka C#
DefaultContractResolver ignorování vlastností ✔️ DefaultJsonTypeInfoResolver – třída
Polymorfní serializace ✔️ Atribut [JsonDerivedType]
Polymorfní deserializace ✔️ Diskriminátor typů u atributu [JsonDerivedType]
Deserializace hodnoty výčtu řetězce ✔️ Deserializace hodnot výčtu řetězců
MissingMemberHandling globální nastavení ✔️ Zpracování chybějících členů
Naplnění vlastností bez zatřikování ✔️ Naplnění vlastností bez zatřikování
ObjectCreationHandling globální nastavení ✔️ Opakované použití místo nahrazení vlastností
Podpora široké škály typů ⚠️ Některé typy vyžadují vlastní převaděče.
Deserializovat odvozený typ na object vlastnosti ⚠️ Nepodporováno, alternativní řešení, ukázka
Deserializace literálu JSON null na typy hodnot bez hodnoty null ⚠️ Nepodporováno, alternativní řešení, ukázka
DateTimeZoneHandling, DateFormatString nastavení ⚠️ Nepodporováno, alternativní řešení, ukázka
JsonConvert.PopulateObject metoda ⚠️ Nepodporováno, alternativní řešení
Podpora atributů System.Runtime.Serialization ⚠️ Nepodporováno, alternativní řešení, ukázka
JsonObjectAttribute ⚠️ Nepodporováno, alternativní řešení
Povolit názvy vlastností bez uvozovek Návrh nepodporuje
Povolit jednoduché uvozovky kolem řetězcových hodnot Návrh nepodporuje
Povolit neřetězcové hodnoty JSON pro vlastnosti řetězce Návrh nepodporuje
TypeNameHandling.All globální nastavení Návrh nepodporuje
Podpora dotazů JsonPath Nepodporováno
Konfigurovatelné limity Nepodporováno

Nejedná se o vyčerpávající seznam Newtonsoft.Json funkcí. Seznam obsahuje řadu scénářů, které byly požadovány v problémech GitHubu nebo příspěvcích StackOverflow . Pokud implementujete alternativní řešení pro některý z zde uvedených scénářů, které aktuálně nemají vzorový kód, a pokud chcete své řešení sdílet, vyberte tuto stránku v části Váš názor v dolní části této stránky. Tím se v úložišti GitHubu této dokumentace vytvoří problém a vypíše ho také v části Váš názor na této stránce.

Rozdíly ve výchozím chování

System.Text.Json je ve výchozím nastavení striktní a zabraňuje jakémukoli odhadu nebo interpretaci jménem volajícího a zdůrazňuje deterministické chování. Knihovna je záměrně navržena tak, aby byla určena pro výkon a zabezpečení. Newtonsoft.Json je ve výchozím nastavení flexibilní. Tento základní rozdíl v návrhu je za mnoha z následujících specifických rozdílů ve výchozím chování.

Nerozlišující velká a malá písmena deserializace

Během deserializace Newtonsoft.Json nerozlišuje ve výchozím nastavení název vlastnosti nerozlišující velká a malá písmena. Ve System.Text.Json výchozím nastavení se rozlišují malá a velká písmena, což poskytuje lepší výkon, protože provádí přesnou shodu. Informace o tom, jak rozlišovat malá a velká písmena porovnávání, naleznete v tématu Porovnávání vlastností bez rozlišování velkých a malých písmen.

Pokud používáte System.Text.Json nepřímo ASP.NET Core, nemusíte dělat nic, abyste získali podobné chování Newtonsoft.Json. ASP.NET Core určuje nastavení pro názvy vlastností camel-casing a porovnávání nerozlišující malá a velká písmena při použití System.Text.Json.

ASP.NET Core také ve výchozím nastavení umožňuje deserializaci uvozových čísel .

Minimální znakové zapouzdření

Během serializace Newtonsoft.Json je relativně permisivní o nechat znaky procházet bez jejich úniku. To znamená, že je nenahrazuje místem \uxxxx , kde xxxx je znakový bod. Když je řídicí, provede to tak, že vygeneruje znak před znakem \ (například " se stane \"). System.Text.Json ve výchozím nastavení uchycuje více znaků, aby poskytovaly hloubkovou ochranu před skriptováním mezi weby (XSS) nebo útoky na zpřístupnění informací a dělá to pomocí šestiznakových sekvencí. System.Text.Json ve výchozím nastavení uchycuje všechny znaky jiné než ASCII, takže nemusíte dělat nic, pokud používáte StringEscapeHandling.EscapeNonAsciiNewtonsoft.Json. System.Text.Json ve výchozím nastavení také umistuje znaky citlivé na HTML. Informace o přepsání výchozího System.Text.Json chování naleznete v tématu Přizpůsobení kódování znaků.

Komentáře

Během deserializace Newtonsoft.Json ignoruje komentáře ve formátu JSON ve výchozím nastavení. Výchozí System.Text.Json hodnotou je vyvolání výjimek pro komentáře, protože specifikace RFC 8259 je neobsahuje. Informace o tom, jak povolit komentáře, naleznete v tématu Povolit komentáře a koncové čárky.

Koncové čárky

Během deserializace Newtonsoft.Json ignoruje koncové čárky ve výchozím nastavení. Ignoruje také více koncových čárek (například [{"Color":"Red"},{"Color":"Green"},,]). Výchozí System.Text.Json hodnotou je vyvolání výjimek pro koncové čárky, protože specifikace RFC 8259 je neumožňuje. Informace o tom System.Text.Json , jak je přijmout, najdete v tématu Povolit komentáře a koncové čárky. Není možné povolit více koncových čárek.

Priorita registrace převaděče

Priorita Newtonsoft.Json registrace pro vlastní převaděče je následující:

Toto pořadí znamená, že vlastní převaděč v Converters kolekci je přepsán převaděčem registrovaným použitím atributu na úrovni typu. Obě tyto registrace jsou přepsány atributem na úrovni vlastnosti.

Priorita System.Text.Json registrace pro vlastní převaděče se liší:

  • Atribut u vlastnosti
  • Converters sbírka
  • Atribut typu

Rozdíl je v tom, že vlastní převaděč v Converters kolekci přepíše atribut na úrovni typu. Záměrem za tímto pořadím priority je provést změny za běhu, které přepíší návrhové volby. Neexistuje způsob, jak změnit prioritu.

Další informace o registraci vlastního převaděče naleznete v tématu Registrace vlastního převaděče.

Maximální hloubka

Nejnovější verze Newtonsoft.Json má ve výchozím nastavení maximální limit hloubky 64. System.Text.Json má také výchozí limit 64 a je konfigurovatelný nastavením JsonSerializerOptions.MaxDepth.

Pokud používáte System.Text.Json nepřímo ASP.NET Core, výchozí limit maximální hloubky je 32. Výchozí hodnota je stejná jako pro vazbu modelu a je nastavena ve třídě JsonOptions.

Řetězce JSON (názvy vlastností a řetězcové hodnoty)

Během deserializace Newtonsoft.Json přijímá názvy vlastností obklopené dvojitými uvozovkami, jednoduchými uvozovkami nebo bez uvozovek. Přijímá řetězcové hodnoty obklopené dvojitými uvozovkami nebo jednoduchými uvozovkami. Například Newtonsoft.Json přijímá následující kód JSON:

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

System.Text.Json Přijímá pouze názvy vlastností a řetězcové hodnoty v dvojitých uvozovkách, protože tento formát je vyžadován specifikací RFC 8259 a je jediným formátem považován za platný JSON.

Výsledkem hodnoty uzavřené v jednoduchých uvozovkách je výjimka JsonException s následující zprávou:

''' is an invalid start of a value.

Neřetězcové hodnoty pro vlastnosti řetězce

Newtonsoft.Json přijímá neřetězcové hodnoty, například číslo nebo literály true a false, pro deserializaci na vlastnosti typu řetězec. Tady je příklad kódu JSON, který Newtonsoft.Json úspěšně deserializuje následující třídu:

{
  "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 nekonstrukční hodnoty deserializuje do vlastností řetězce. Hodnota, která není řetězec přijatá pro pole řetězce, má za následek hodnotu JsonException s následující zprávou:

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

Scénáře s využitím JsonSerializeru

Některé z následujících scénářů nejsou integrované funkce podporované, ale alternativní řešení jsou možná. Alternativní řešení jsou vlastní převaděče, které nemusí poskytovat úplnou paritu s funkcemi Newtonsoft.Json . Pro některé z nich je ukázkový kód k dispozici jako příklady. Pokud se na tyto Newtonsoft.Json funkce spoléháte, migrace bude vyžadovat úpravy vašich objektů .NET nebo jiných změn kódu.

V některých z následujících scénářů nejsou alternativní řešení praktická nebo možná. Pokud se na tyto Newtonsoft.Json funkce spoléháte, migrace nebude možná bez významných změn.

Povolit nebo zapsat čísla v uvozovkách

Newtonsoft.Json může serializovat nebo deserializovat čísla reprezentovaná řetězci JSON (obklopené uvozovkami). Může například přijmout: {"DegreesCelsius":"23"} místo {"DegreesCelsius":23}. Pokud chcete toto chování povolit, System.Text.Jsonnastavte JsonSerializerOptions.NumberHandling na WriteAsString hodnotu nebo AllowReadingFromStringpoužijte atribut [JsonNumberHandling].

Pokud používáte System.Text.Json nepřímo ASP.NET Core, nemusíte dělat nic, abyste získali podobné chování Newtonsoft.Json. ASP.NET Core určuje výchozí hodnoty webu při použití System.Text.Jsona výchozí hodnoty webu umožňují uvozovávání čísel.

Další informace najdete v tématu Povolení nebo zápis čísel v uvozovkách.

Určení konstruktoru, který se má použít při deserializaci

Atribut Newtonsoft.Json[JsonConstructor] umožňuje určit, který konstruktor má volat při deserializaci do POCO.

System.Text.Jsontaké atribut [JsonConstructor]. Další informace naleznete v tématu Neměnné typy a záznamy.

Podmíněně ignorovat vlastnost

Newtonsoft.Json má několik způsobů, jak podmíněně ignorovat vlastnost serializace nebo deserializace:

  • DefaultContractResolver umožňuje vybrat vlastnosti, které chcete zahrnout nebo ignorovat na základě libovolných kritérií.
  • Toto NullValueHandling nastavení DefaultValueHandling vám JsonSerializerSettings umožní určit, že se mají ignorovat všechny vlastnosti s hodnotou null nebo výchozí hodnotou.
  • Nastavení NullValueHandling atributu DefaultValueHandling[JsonProperty] umožňují určit jednotlivé vlastnosti, které by se měly ignorovat při nastavení hodnoty null nebo výchozí hodnoty.

System.Text.Json poskytuje následující způsoby, jak při serializaci ignorovat vlastnosti nebo pole:

Kromě toho můžete v .NET 7 a novějších verzích přizpůsobit kontrakt JSON tak, aby ignoroval vlastnosti na základě libovolných kritérií. Další informace naleznete v tématu Vlastní kontrakty.

Veřejná a neveřejná pole

Newtonsoft.Json může serializovat a deserializovat pole i vlastnosti.

Použijte System.Text.Jsonglobální JsonSerializerOptions.IncludeFields nastavení nebo atribut [JsonInclude] k zahrnutí veřejných polí při serializaci nebo deserializaci. Příklad najdete v části Zahrnout pole.

Zachování odkazů na objekt a zpracování smyček

Ve výchozím nastavení Newtonsoft.Json serializuje podle hodnoty. Pokud například objekt obsahuje dvě vlastnosti, které obsahují odkaz na stejný Person objekt, budou hodnoty Person vlastností tohoto objektu duplikovány ve formátu JSON.

Newtonsoft.Json PreserveReferencesHandling má nastaveníJsonSerializerSettings, které umožňuje serializovat odkazem:

  • Metadata identifikátoru se přidají do formátu JSON vytvořeného pro první Person objekt.
  • Json vytvořený pro druhý Person objekt obsahuje odkaz na tento identifikátor místo hodnot vlastností.

Newtonsoft.JsonReferenceLoopHandling také nastavení, které umožňuje ignorovat cyklické odkazy místo vyvolání výjimky.

Chcete-li zachovat odkazy a zpracovat cyklické odkazy v System.Text.Json, je nastavena JsonSerializerOptions.ReferenceHandler na Preservehodnotu . Nastavení ReferenceHandler.Preserve je ekvivalentní hodnotě PreserveReferencesHandling = PreserveReferencesHandling.All in Newtonsoft.Json.

Možnost ReferenceHandler.IgnoreCycles má podobné chování jako Newtonsoft.JsonReferenceLoopHandling.Ignore. Jedním rozdílem je, že System.Text.Json implementace nahrazuje smyčky odkazů tokenem null JSON místo ignorování odkazu na objekt. Další informace najdete v tématu Ignorování cyklických odkazů.

Newtonsoft.Json Podobně jako ReferenceResolverSystem.Text.Json.Serialization.ReferenceResolver třída definuje chování zachování odkazů na serializaci a deserializaci. Vytvořte odvozenou třídu pro určení vlastního chování. Příklad najdete v tématu GuidReferenceResolver.

Některé související Newtonsoft.Json funkce nejsou podporované:

Další informace naleznete v tématu Zachování odkazů a zpracování cyklických odkazů.

Slovník s klíčem bez řetězce

Obě Newtonsoft.Json a System.Text.Json podporují kolekce typu Dictionary<TKey, TValue>. Informace o podporovaných typech klíčů najdete v tématu Podporované typy klíčů.

Upozornění

Deserializace na místo, Dictionary<TKey, TValue> kde TKey je zadáno jako cokoli jiného, než string by mohlo v aplikaci, která využívá, představovat ohrožení zabezpečení. Další informace najdete v tématu dotnet/runtime#4761.

Typy bez integrované podpory

System.Text.Json neposkytuje integrovanou podporu pro následující typy:

Vlastní převaděče je možné implementovat pro typy, které nemají integrovanou podporu.

Polymorfní serializace

Newtonsoft.Json automaticky provádí polymorfní serializaci. Počínaje rozhraním .NET 7 System.Text.Json podporuje polymorfní serializaci prostřednictvím atributu JsonDerivedTypeAttribute . Další informace naleznete v tématu Serializace vlastností odvozených tříd.

Polymorfní deserializace

Newtonsoft.Json TypeNameHandling má nastavení, které při serializaci přidává metadata názvu typu do formátu JSON. Používá metadata při deserializaci k polymorfní deserializaci. Počínaje rozhraním .NET 7 System.Text.Json se při provádění polymorfní deserializace spoléhá na diskriminující informace o typu. Tato metadata se vygenerují ve formátu JSON a použijí se při deserializaci k určení, zda se má deserializovat na základní typ nebo odvozený typ. Další informace naleznete v tématu Serializace vlastností odvozených tříd.

Chcete-li podporovat polymorfní deserializaci ve starších verzích .NET, vytvořte převaděč, jako je příklad v návodu k zápisu vlastních převaděčů.

Deserializace hodnot výčtu řetězců

Ve výchozím nastavení System.Text.Json nepodporuje deserializaci hodnot výčtu řetězců, zatímco Newtonsoft.Json to dělá. Například následující kód vyvolá JsonException:

string json = "{ \"Text\": \"Hello\", \"Enum\": \"Two\" }";
var _ = JsonSerializer.Deserialize<MyObj>(json); // Throws exception.

class MyObj
{
    public string Text { get; set; } = "";
    public MyEnum Enum { get; set; }
}

enum MyEnum
{
    One,
    Two,
    Three
}

Pomocí převaděče však můžete povolit deserializaci hodnot výčtu JsonStringEnumConverter řetězců. Další informace naleznete v tématu Výčty jako řetězce.

Deserializace vlastností objektu

Při Newtonsoft.Json deserializaci na Object, to:

  • Odvodí typ primitivních hodnot v datové části JSON (jiné než null) a vrátí uloženou stringhodnotu , long, double, booleannebo DateTime jako boxovaný objekt. Primitivní hodnoty jsou jednoduché hodnoty JSON, jako je číslo JSON, řetězec, true, falsenebo null.
  • JObject Vrátí hodnotu nebo JArray pro komplexní hodnoty v datové části JSON. Komplexní hodnoty jsou kolekce párů klíč-hodnota JSON v rámci složených závorek ({}) nebo seznamů hodnot v hranatých závorkách ([]). Vlastnosti a hodnoty v závorkách nebo závorkách můžou mít další vlastnosti nebo hodnoty.
  • Vrátí nulový odkaz, pokud datová část obsahuje null literál JSON.

System.Text.Json ukládá rámečky JsonElement pro primitivní i komplexní hodnoty při každé deserializaci Objectna , například:

  • Vlastnost object .
  • Hodnota object slovníku.
  • Jedná se o maticovou object hodnotu.
  • Kořen object.

System.Text.Json Považuje null však za stejný Newtonsoft.Json jako a vrátí nulový odkaz, pokud datová část obsahuje null literál JSON.

Chcete-li implementovat odvození typu pro object vlastnosti, vytvořte převaděč, jako je příklad v postupu zápisu vlastních převaděčů.

Deserializace typu null na typ bez hodnoty null

Newtonsoft.Json nevyvolá výjimku v následujícím scénáři:

  • NullValueHandling je nastavena na Ignorehodnotu a
  • Během deserializace json obsahuje hodnotu null pro typ hodnoty bez hodnoty null.

Ve stejném scénáři System.Text.Json vyvolá výjimku. (Odpovídající nastavení zpracování null je System.Text.JsonJsonSerializerOptions.IgnoreNullValues = .)true

Pokud vlastníte cílový typ, nejlepším alternativním řešením je vytvořit vlastnost s možnou hodnotou null (například změnit int na int?).

Dalším alternativním řešením je vytvořit převaděč pro typ, například následující příklad, který zpracovává hodnoty null pro DateTimeOffset typy:

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

Zaregistrujte tento vlastní převaděč pomocí atributu ve vlastnosti nebo přidáním převaděčeConverters do kolekce.

Poznámka: Předchozí převaděč zpracovává hodnoty null odlišně než Newtonsoft.Json u objektů POCOs, které určují výchozí hodnoty. Předpokládejme například, že následující kód představuje cílový objekt:

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

A předpokládejme, že následující JSON je deserializován pomocí předchozího převaděče:

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

Po deserializaci Date má vlastnost hodnotu 1/1/0001 (default(DateTimeOffset)), tj. hodnota nastavená v konstruktoru je přepsána. Vzhledem ke stejnému POCO a JSON Newtonsoft.Json by deserializace ponechá ve Date vlastnosti 1.1.2001.

Deserializace na neměnné třídy a struktury

Newtonsoft.Json může deserializovat na neměnné třídy a struktury, protože může používat konstruktory, které mají parametry.

Pomocí System.Text.Jsonatributu [JsonConstructor] zadejte použití parametrizovaného konstruktoru. Záznamy v jazyce C# 9 jsou také neměnné a podporují se jako cíle deserializace. Další informace naleznete v tématu Neměnné typy a záznamy.

Požadované vlastnosti

V Newtonsoft.Jsonparametru určíte, že vlastnost je vyžadována nastavením Required atributu [JsonProperty] . Newtonsoft.Json vyvolá výjimku, pokud ve formátu JSON není přijata žádná hodnota pro vlastnost označenou jako povinnou.

Počínaje rozhraním .NET 7 můžete použít modifikátor jazyka C# required nebo JsonRequiredAttribute atribut u požadované vlastnosti. System.Text.Json vyvolá výjimku, pokud datová část JSON neobsahuje hodnotu pro označenou vlastnost. Další informace naleznete v tématu Povinné vlastnosti.

Zadání formátu data

Newtonsoft.Json poskytuje několik způsobů řízení, jak vlastnosti DateTime a DateTimeOffset typy jsou serializovány a deserializovány:

  • Nastavení DateTimeZoneHandling lze použít k serializaci všech DateTime hodnot jako data UTC.
  • Nastavení DateFormatString a DateTime převaděče lze použít k přizpůsobení formátu řetězců kalendářních dat.

System.Text.Json podporuje ISO 8601-1:2019 včetně profilu RFC 3339. Tento formát je široce přijímaný, jednoznačný a provádí přesné odezvy. Pokud chcete použít jiný formát, vytvořte vlastní převaděč. Například následující převaděče serializují a deserializují JSON, které používají formát Epoch unixu s posunem časového pásma (hodnoty, jako /Date(1590863400000-0700)/ jsou nebo /Date(1590863400000)/):

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

    public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        string formatted = reader.GetString()!;
        Match match = s_regex.Match(formatted);

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

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

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

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

        string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");

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

    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        string formatted = reader.GetString()!;
        Match match = s_regex.Match(formatted);

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

        return s_epoch.AddMilliseconds(unixTime);
    }

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

        string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime})/");
        writer.WriteStringValue(formatted);
    }
}

Další informace naleznete v tématu DateTime a DateTimeOffset podpora v System.Text.Json.

Zpětná volání

Newtonsoft.Json umožňuje spouštět vlastní kód v několika bodech procesu serializace nebo deserializace:

  • OnDeserializing (při zahájení deserializace objektu)
  • OnDeserialized (po dokončení deserializace objektu)
  • OnSerializing (při zahájení serializace objektu)
  • OnSerialized (po dokončení serializace objektu)

System.Text.Json zveřejňuje stejná oznámení během serializace a deserializace. Pokud je chcete použít, implementujte jedno nebo více následujících rozhraní z System.Text.Json.Serialization oboru názvů:

Tady je příklad, který kontroluje vlastnost null a zapisuje zprávy na začátku a na konci serializace a deserializace:

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=

Kód OnDeserializing nemá přístup k nové instanci POCO. Chcete-li manipulovat s novou instancí POCO na začátku deserializace, vložte tento kód do konstruktoru POCO.

Neveřejná vlastnost setters a getters

Newtonsoft.Json může používat privátní a interní vlastnosti setters a getters prostřednictvím atributu JsonProperty .

System.Text.Jsonpodporuje privátní a interní setters a getters prostřednictvím atributu [JsonInclude]. Vzorový kód naleznete v tématu Neveřejné přístupové objekty vlastností.

Naplnění existujících objektů

Metoda JsonConvert.PopulateObject deserializuje Newtonsoft.Json dokument JSON do existující instance třídy místo vytvoření nové instance. System.Text.Json vždy vytvoří novou instanci cílového typu pomocí výchozího veřejného konstruktoru bez parametrů. Vlastní převaděče mohou deserializovat na existující instanci.

Opakované použití místo nahrazení vlastností

Počínaje rozhraním .NET 8 System.Text.Json podporuje opakované použití inicializovaných vlastností, nikoli jejich nahrazení. Existují určité rozdíly v chování, o kterých si můžete přečíst v návrhu rozhraní API.

Další informace naleznete v tématu Naplnění inicializovaných vlastností.

Naplnění vlastností bez zatřikování

Počínaje rozhraním .NET 8 System.Text.Json podporuje naplnění vlastností, včetně těch, které nemají setter. Další informace naleznete v tématu Naplnění inicializovaných vlastností.

Zásady pojmenování hadího případu

System.Text.Json obsahuje předdefinované zásady pojmenování pro případ hadů. U některých vstupů ale existují určité rozdíly Newtonsoft.Json v chování. Následující tabulka uvádí některé z těchto rozdílů při převodu JsonNamingPolicy.SnakeCaseLower vstupu pomocí zásad.

Vstup Newtonsoft.Json výsledek System.Text.Json výsledek
"AB1" "a_b1" "ab1"
"SHA512Managed" "sh_a512_managed" "sha512_managed"
"abc123DEF456" "abc123_de_f456" "abc123_def456"
"KEBAB-CASE" "keba_b-_case" "kebab-case"

Atributy System.Runtime.Serialization

System.Runtime.Serialization atributy, jako DataContractAttributeje , DataMemberAttributea IgnoreDataMemberAttribute umožňují definovat kontrakt dat. Kontrakt dat je formální smlouva mezi službou a klientem, která abstraktivně popisuje data, která se mají vyměňovat. Kontrakt dat přesně definuje, které vlastnosti jsou serializovány pro výměnu.

System.Text.Json nemá integrovanou podporu těchto atributů. Od verze .NET 7 ale můžete k přidání podpory použít vlastní překladač typů. Ukázku najdete v tématu ZCS. DataContractResolver.

Osmičková čísla

Newtonsoft.Json zachází s čísly s úvodní nulou jako osmičkovými čísly. System.Text.Json neumožňuje úvodní nuly, protože specifikace RFC 8259 je neumožňuje.

Zpracování chybějících členů

Pokud json, který se deserializuje, zahrnuje vlastnosti, které chybí v cílovém typu, lze nakonfigurovat tak, Newtonsoft.Json aby vyvolaly výjimky. Ve výchozím nastavení System.Text.Json ignoruje další vlastnosti ve formátu JSON, s výjimkou případů, kdy použijete atribut [JsonExtensionData].

V .NET 8 a novějších verzích můžete nastavit předvolby, jestli chcete přeskočit nebo zakázat nenamapované vlastnosti JSON, a to jedním z následujících způsobů:

JsonObjectAttribute

Newtonsoft.Json má atribut, který JsonObjectAttributelze použít na úrovni typu k řízení, které členy jsou serializovány, jak null se hodnoty zpracovávají a zda jsou požadovány všechny členy. System.Text.Json nemá žádný ekvivalentní atribut, který lze použít u typu. U některých chování, jako null je zpracování hodnot, můžete buď nakonfigurovat stejné chování na globální JsonSerializerOptions , nebo jednotlivě u každé vlastnosti.

Vezměte v úvahu následující příklad, který používá Newtonsoft.Json.JsonObjectAttribute k určení, že všechny null vlastnosti by měly být ignorovány:

[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class Person { ... }

V System.Text.Jsonaplikaci můžete nastavit chování pro všechny typy a vlastnosti:

JsonSerializerOptions options = new()
{
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};

string json = JsonSerializer.Serialize<Person>(person, options);

Nebo můžete chování jednotlivých vlastností nastavit samostatně:

public class Person
{
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Name { get; set; }

    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public int? Age { get; set; }
}

Dále vezměte v úvahu následující příklad, který používá Newtonsoft.Json.JsonObjectAttribute k určení, že všechny vlastnosti člena musí být přítomny ve formátu JSON:

[JsonObject(ItemRequired = Required.Always)]
public class Person { ... }

Stejné chování System.Text.Json můžete dosáhnout přidáním modifikátoru jazyka C# required nebo JsonRequiredAttributedo každé vlastnosti. Další informace naleznete v tématu Povinné vlastnosti.

public class Person
{
    [JsonRequired]
    public string? Name { get; set; }

    public required int? Age { get; set; }
}

TraceWriter

Newtonsoft.Json umožňuje ladit pomocí protokolu TraceWriter , které jsou generovány serializací nebo deserializací. System.Text.Json neprovádí protokolování.

JsonDocument a JsonElement ve srovnání s JTokenem (například JObject, JArray)

System.Text.Json.JsonDocument poskytuje možnost parsovat a sestavit model DOM (Document Object Model) jen pro čtení z existujících datových částí JSON. DOM poskytuje náhodný přístup k datům v datové části JSON. K elementům JSON, které tvoří datovou část, je možné přistupovat prostřednictvím JsonElement typu. Tento JsonElement typ poskytuje rozhraní API pro převod textu JSON na běžné typy .NET. JsonDocument RootElement zveřejňuje vlastnost.

Počínaje rozhraním .NET 6 můžete parsovat a sestavit proměnlivý dom z existujících datových částí JSON pomocí JsonNode typu a dalších typů v System.Text.Json.Nodes oboru názvů. Další informace naleznete v tématu Použití JsonNode.

JsonDocument je IDisposable

JsonDocument vytvoří zobrazení dat v paměti do vyrovnávací paměti ve fondu. Proto na rozdíl od JObject , JArrayNewtonsoft.JsonJsonDocument typ implementuje IDisposable a je třeba použít uvnitř bloku using. Další informace najdete v tématu JsonDocument je IDisposable.

JsonDocument je jen pro čtení

DOM System.Text.Json nemůže přidávat, odebírat ani upravovat elementy JSON. Je navržený tak, aby byl výkon a snížil přidělení pro analýzu běžných velikostí datových částí JSON (to znamená < 1 MB).

JsonElement je sjednocující struktura.

JsonDocument zpřístupňuje RootElement jako vlastnost typu JsonElement, což je sjednocující typ struktury, který zahrnuje všechny elementy JSON. Newtonsoft.Jsonpoužívá vyhrazené hierarchické typy jako JObject, , JArrayJTokena tak dále. JsonElement je to, co můžete prohledávat a vyčíslovat, a můžete použít JsonElement k materializaci elementů JSON do typů .NET.

Počínaje rozhraním .NET 6 můžete použít JsonNode typ a typy v System.Text.Json.Nodes oboru názvů, který odpovídá JObject, JArraya JToken. Další informace naleznete v tématu Použití JsonNode.

Vyhledání dílčích elementů ve formátu JsonDocument a JsonElement

Vyhledá tokeny JSON, které používají JObject nebo JArray z Newtonsoft.Json nich mají tendenci být poměrně rychlé, protože se jedná o vyhledávání v některém slovníku. Při porovnávání JsonElement vyhledávání vyžaduje sekvenční vyhledávání vlastností, a proto jsou relativně pomalé (například při použití TryGetProperty). System.Text.Json je navržen tak, aby minimalizoval počáteční čas analýzy místo doby vyhledávání. Další informace najdete v tématu Jak hledat v souboru JsonDocument a JsonElement dílčí prvky.

Utf8JsonReader vs. JsonTextReader

System.Text.Json.Utf8JsonReaderje vysoce výkonná, nízká alokace, čtečka jen pro čtení textu JSON s kódováním UTF-8, čtení z bajtu <>ReadOnlySpannebo > ReadOnlySequence. Jedná se Utf8JsonReader o typ nízké úrovně, který lze použít k vytváření vlastních analyzátorů a deserializérů.

Utf8JsonReader je ref – struktura

JsonTextReader In Newtonsoft.Json je třída. Typ Utf8JsonReader se liší v tom, že se jedná o strukturu odkazu. Další informace najdete v tématu omezení struktury ref pro Utf8JsonReader.

Čtení hodnot null do typů hodnot s možnou hodnotou null

Newtonsoft.Jsonposkytuje rozhraní API, která vrací Nullable<T>, například ReadAsBoolean, která za vás zpracovává NullTokenType vrácením .bool? Integrovaná System.Text.Json rozhraní API vrací pouze typy hodnot, které nemají hodnotu null. Další informace naleznete v tématu Čtení hodnot null do typů hodnot s možnou hodnotou null.

Vícecílový cíl pro čtení JSON

Pokud potřebujete pokračovat v používání Newtonsoft.Json pro určité cílové architektury, můžete mít více cílů a mít dvě implementace. To ale není triviální a vyžadovalo by to určité #ifdefs a zdrojové duplicity. Jedním ze způsobů, jak sdílet co nejvíce kódu, je vytvořit obálku ref struct kolem Utf8JsonReader a Newtonsoft.Json.JsonTextReader. Tento obálka by sjednotila veřejnou plochu při izolování rozdílů v chování. Díky tomu můžete izolovat změny hlavně ve konstrukci typu spolu s předáváním nového typu podle odkazu. Toto je vzor, který knihovna Microsoft.Extensions.DependencyModel sleduje:

Utf8JsonWriter vs. JsonTextWriter

System.Text.Json.Utf8JsonWriter je vysoce výkonný způsob, jak psát kódovaný text JSON UTF-8 z běžných typů .NET, jako je String, Int32a DateTime. Zapisovač je typ nízké úrovně, který lze použít k sestavení vlastních serializátorů.

Zápis nezpracovaných hodnot

Newtonsoft.Json má metodu, která zapisuje nezpracovaný WriteRawValue kód JSON, kde se očekává hodnota. System.Text.Json má přímý ekvivalent: Utf8JsonWriter.WriteRawValue. Další informace najdete v tématu Zápis nezpracovaných souborů JSON.

Přizpůsobení formátu JSON

JsonTextWriter obsahuje následující nastavení, pro která Utf8JsonWriter nemá žádný ekvivalent:

  • QuoteChar – Určuje znak, který se má použít k obklopování řetězcových hodnot. Utf8JsonWriter vždy používá dvojité uvozovky.
  • QuoteName – Určuje, zda se mají názvy vlastností ohraničovaly uvozovkami. Utf8JsonWriter vždy je obklopuje uvozovkami.

Od verze .NET 9 můžete přizpůsobit znak a velikost odsazení pro Utf8JsonWriter použití možností vystavených strukturou JsonWriterOptions :

JsonTextWriter obsahuje následující nastavení, pro která Utf8JsonWriter nemá žádný ekvivalent:

  • Odsazení – Určuje, kolik znaků se má odsadit. Utf8JsonWriter vždy odsadí o 2 znaky.
  • IndentChar – Určuje znak, který se má použít pro odsazení. Utf8JsonWriter vždy používá prázdné znaky.
  • QuoteChar – Určuje znak, který se má použít k obklopování řetězcových hodnot. Utf8JsonWriter vždy používá dvojité uvozovky.
  • QuoteName – Určuje, zda se mají názvy vlastností ohraničovaly uvozovkami. Utf8JsonWriter vždy je obklopuje uvozovkami.

Neexistují žádná alternativní řešení, která by vám umožnila přizpůsobit json vytvořený Utf8JsonWriter těmito způsoby.

Hodnoty časového rozsahu, identifikátoru URI nebo znaku

JsonTextWriter poskytuje WriteValue metody pro hodnoty TimeSpan, Uri a char . Utf8JsonWriter nemá ekvivalentní metody. Místo toho tyto hodnoty naformátovat jako řetězce (například voláním ToString()) a voláním WriteStringValue.

Vícecílový pro zápis JSON

Pokud potřebujete pokračovat v používání Newtonsoft.Json pro určité cílové architektury, můžete mít více cílů a mít dvě implementace. To ale není triviální a vyžadovalo by to určité #ifdefs a zdrojové duplicity. Jedním ze způsobů, jak sdílet co nejvíce kódu, je vytvořit obálku kolem Utf8JsonWriter a Newtonsoft.Json.JsonTextWriter. Tento obálka by sjednotila veřejnou plochu při izolování rozdílů v chování. Díky tomu můžete izolovat změny hlavně v konstrukci typu. Knihovna Microsoft.Extensions.DependencyModel :

TypeNameHandling.All se nepodporuje

Rozhodnutí vyloučit TypeNameHandling.Allz ní ekvivalentní funkce System.Text.Json bylo záměrné. Povolení datové části JSON zadat vlastní informace o typu je běžným zdrojem ohrožení zabezpečení ve webových aplikacích. Konkrétně konfigurace Newtonsoft.Json umožňuje TypeNameHandling.All vzdálenému klientovi vložit celou spustitelné aplikaci do samotné datové části JSON, aby během deserializace webové aplikace extrahovala a spustila vložený kód. Další informace najdete v pátek v 13. útoku JSON na PowerPoint a pátek podrobnosti o 13. útoku JSON.

Nepodporované dotazy na cestu JSON

DOM JsonDocument nepodporuje dotazování pomocí cesty JSON.

JsonNode V systému DOM má každá JsonNode instance metoduGetPath, která vrací cestu k uzlu. Neexistuje ale žádné integrované rozhraní API pro zpracování dotazů založených na řetězcích dotazu cesty JSON.

Další informace najdete v problému s dotnet/runtime #31068 Na GitHubu.

Některá omezení nelze konfigurovat.

System.Text.Json nastaví omezení, která se nedají změnit u některých hodnot, například maximální velikost tokenu ve znaky (166 MB) a v základu 64 (125 MB). Další informace najdete JsonConstants ve zdrojovém kódu a problému s GitHubem dotnet/runtime č. 39953.

NaN, Nekonečno, -Nekonečno

Newtonsoft parsuje NaNa Infinity-Infinity řetězcové tokeny JSON. S System.Text.Json, použít JsonNumberHandling.AllowNamedFloatingPointLiterals. Informace o tom, jak toto nastavení použít, najdete v tématu Povolit nebo napsat čísla v uvozovkách.

Použití GitHub Copilotu k migraci

Pomoc s kódováním můžete získat z GitHub Copilotu pro migraci kódu z Newtonsoft.Json do System.Text.Json v integrovaném vývojovém prostředí (IDE). Výzvu můžete přizpůsobit podle svých požadavků.

Příklad výzvy ke kopírování chatu

convert the following code to use System.Text.Json
Product product = new Product();

product.Name = "Apple";
product.ExpiryDate = new DateTime(2024, 08, 08);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };

string output = JsonConvert.SerializeObject(product);
Console.WriteLine(output);

GitHub Copilot využívá technologii AI, takže jsou možná překvapení a chyby. Další informace najdete v nejčastějších dotazech ke copilotu.

Přečtěte si další informace o GitHub Copilotu v sadě Visual Studio a GitHub Copilotu ve VS Code.

Další materiály