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 formátu a deserializaci z formátu 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

Návod

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

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. Pro získání podobného chování u System.Text.Json může být třeba použít atribut nebo globální možnost.
  • ⚠✔ Nepodporováno, ale alternativní řešení je možné. Alternativní řešení jsou vlastní převaděče, které nemusí poskytovat úplnou rovnocennost s funkcionalitou 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í ve formátu "snake-case" ✔️ Zásady pojmenování hadího případu
Minimální escapování znaků ✔️ 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, nastavitelná
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 neřetězcovým klíčem ✔️ Podporovaný
Podpora neveřejných nastavovačů a získávačů vlastností ✔️ Atribut JsonInclude
Atribut [JsonConstructor] ✔️ [JsonConstructor] – atribut
ReferenceLoopHandling globální nastavení ✔️ Globální nastavení ReferenceHandling
Zpětná volání ✔️ Zpětná volání
NaN, Nekonečno, -Nekonečno ✔️ Podporovaný
Requirednastavení atributu [JsonProperty] ✔️ Atribut [JsonRequired] a požadovaný modifikátor jazyka C#
DefaultContractResolver ignorovat vlastnosti ✔️ DefaultJsonTypeInfoResolver – třída
Polymorfní serializace ✔️ Atribut [JsonDerivedType]
Polymorfní deserializace ✔️ Diskriminátor typů u atributu [JsonDerivedType]
Deserializace hodnoty výčtu řetězce ✔️ Deserializace hodnot řetězcových výčtů
MissingMemberHandling globální nastavení ✔️ Zpracování chybějících členů
Naplnění vlastností bez zatřikování ✔️ Nastavení vlastností bez setterů
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 Nepodporováno dle návrhu
Povolit jednoduché uvozovky kolem řetězcových hodnot Nepodporováno dle návrhu
Povolit neřetězcové hodnoty JSON pro vlastnosti řetězce Nepodporováno dle návrhu
TypeNameHandling.All globální nastavení Nepodporováno dle návrhu
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 uvede ho také v sekci 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í.

Deserializace bez rozlišení velikosti písmen

Během deserializace Newtonsoft.Json ve výchozím nastavení provádí porovnávání názvů vlastností bez rozlišení velkých a malých písmen. Ve výchozím nastavení se rozlišují malá a velká písmena, což nabízí lepší výkon díky tomu, že provádí přesné porovnání. Informace o tom, jak provést porovnávání bez ohledu na velikost písmen, naleznete v tématu Porovnávání vlastností bez ohledu na velikost písmen.

Pokud používáte System.Text.Json nepřímo prostřednictvím ASP.NET Core, nemusíte dělat nic, abyste dosáhli chování jako 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 čísel v uvozovkách.

Minimální escapování znaků

Během serializace je Newtonsoft.Json relativně tolerantní k tomu, aby nechal znaky procházet bez jejich escapování. To znamená, že je nenahrazuje místem \uxxxx , kde xxxx je znakový bod. Když se z nich něco dostane, provede to tak, že vygeneruje \ před znakem (například " se změní na \"). 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í uniká všechny znaky jiné než ASCII, takže nemusíte dělat nic, pokud používáte StringEscapeHandling.EscapeNonAscii v Newtonsoft.Json. System.Text.Json ve výchozím nastavení také umistuje znaky citlivé na HTML. Informace o tom, jak přepsat výchozí chování System.Text.Json, 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 použití více koncových čárek.

Pořadí 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 kolekci Converters je nahrazen převaděčem, který je registrován 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 přednosti je umožnit dynamické změny, které převáží nad návrhovými volbami. 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 pomocí 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 řetězcové vlastnosti

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 JSON, který Newtonsoft.Json úspěšně deserializuje do následující třídy:

{
  "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 nedeserializuje neřetězcové hodnoty do vlastností řetězce. Pokud je pro pole řetězce přijata hodnota, která není řetězec, dojde k 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 psát čí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 v System.Text.Json, nastavte JsonSerializerOptions.NumberHandling na WriteAsString nebo AllowReadingFromString, nebo použijte atribut [JsonNumberHandling].

Pokud používáte System.Text.Json nepřímo prostřednictvím ASP.NET Core, nemusíte dělat nic, abyste dosáhli chování jako 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.Json také má 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í.
  • Nastavení NullValueHandling a DefaultValueHandling na JsonSerializerSettings vám 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 v System.Text.Json globální nastavení JsonSerializerOptions.IncludeFields nebo atribut [JsonInclude] k zahrnutí veřejných polí při serializaci nebo deserializaci. Příklad najdete v části Zahrnout pole.

Zachovat odkazy na objekty a zpracovat smyčky

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á na JsonSerializerSettings nastavení, které umožňuje serializovat prostřednictvím odkazu:

  • 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.Json má také ReferenceLoopHandling nastavení, které umožňuje ignorovat cyklické odkazy, aniž by vyvolalo výjimku.

Chcete-li zachovat odkazy a zpracovat cyklické odkazy v System.Text.Json, nastavte JsonSerializerOptions.ReferenceHandler na Preserve. 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.JsonTřída ReferenceResolver podobně jako System.Text.Json.Serialization.ReferenceResolver definuje chování pro zachování odkazů při 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 neřetězcovým klíčem

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 Dictionary<TKey, TValue>, kde je TKey zadáno jako cokoli jiného než string, by mohla představovat bezpečnostní riziko v aplikaci, která to využívá. 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 .NET 7 se System.Text.Json při provádění polymorfní deserializace spoléhá na informace určující typ. 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 řetězcových výčtů

Ve výchozím nastavení System.Text.Json nepodporuje deserializaci řetězcových hodnot výčtu, zatímco Newtonsoft.Json ano. 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

Když se Newtonsoft.Json deserializuje na Object, to:

  • Odvodí typ primitivních hodnot v JSON payloadu (jiné než null) a vrátí uložené string, long, double, boolean nebo DateTime jako obalený objekt. Primitivní hodnoty jsou jednoduché hodnoty JSON, jako je číslo JSON, řetězec, true, falsenebo null.
  • Vrátí JObject nebo JArray u komplexních hodnot 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 ve složených nebo hranatých závorkách mohou mít další vlastnosti nebo hodnoty.
  • Vrátí nulový odkaz, pokud datová část obsahuje null literál JSON.

System.Text.Json ukládá zabalené JsonElement pro primitivní i komplexní hodnoty při každé deserializaci na Object, například:

  • Vlastnost object.
  • Hodnota object slovníku.
  • Hodnota pole object.
  • Kořen object.

System.Text.Json zpracovává null stejně jako Newtonsoft.Json, a vrátí nulový odkaz, pokud datová část obsahuje literál JSON null.

Chcete-li implementovat odvození typu pro object vlastnosti, vytvořte převaděč podle příkladu v části „Jak psát vlastní převaděče“.

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 nulovou hodnotu pro nenulový hodnotový typ.

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. Při použití stejného POCO a JSON Newtonsoft.Json by po deserializaci zůstalo v Date vlastnosti datum 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ů, jak řídit serializaci a deserializaci vlastností typů DateTime a DateTimeOffset:

  • Nastavení DateTimeZoneHandling lze použít k serializaci všech DateTime hodnot jako data UTC.
  • Nastavení DateFormatString a převodníky DateTime lze použít k úpravě formátu řetězců s daty.

System.Text.Json podporuje ISO 8601-1:2019 včetně profilu RFC 3339. Tento formát je široce přijímaný, jednoznačný a umožňuje přesné opakované cykly. 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žívá formát Unix epoch s nebo bez posunu časového pásma (hodnoty, jako /Date(1590863400000-0700)/ nebo /Date(1590863400000)/):

sealed class UnixEpochDateTimeOffsetConverter : System.Text.Json.Serialization.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, NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
                || !int.TryParse(match.Groups[3].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
                || !int.TryParse(match.Groups[4].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
        {
            throw new System.Text.Json.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 = value.ToUnixTimeMilliseconds();

        TimeSpan utcOffset = value.Offset;

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

        writer.WriteStringValue(formatted);
    }
}
sealed class UnixEpochDateTimeConverter : System.Text.Json.Serialization.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, NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime))
        {
            throw new System.Text.Json.JsonException();
        }

        return s_epoch.AddMilliseconds(unixTime);
    }

    public override void Write(
        Utf8JsonWriter writer,
        DateTime value,
        JsonSerializerOptions options)
    {
        long unixTime = (value - s_epoch).Ticks / TimeSpan.TicksPerMillisecond;

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

Další informace naleznete v tématu podporu DateTime a DateTimeOffset 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é nastavovače a získávače vlastností

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

System.Text.Json podporuje soukromé a vnitřní nastavovače a získavače prostřednictvím atributu [JsonInclude]. Vzorový kód naleznete v části Neveřejné přístupové metody 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 do existující instance.

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ů. Ale pro některé vstupy existují určité rozdíly v chování Newtonsoft.Json. Následující tabulka uvádí některé z těchto rozdílů při převodu vstupu pomocí zásady JsonNamingPolicy.SnakeCaseLower.

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 je DataContractAttribute, DataMemberAttribute a IgnoreDataMemberAttribute, umožňují definovat datový kontrakt. 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.

Řešení 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. Pro některá chování, jako je null zpracování hodnot, můžete nakonfigurovat stejné chování buď na globální úroveň JsonSerializerOptions nebo individuálně pro každou vlastnost.

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 tak, že použijete TraceWriter k zobrazení logů generovaných 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 odhaluje vlastnost RootElement.

Počínaje rozhraním .NET 6 můžete parsovat a sestavit proměnlivý DOM z existujících datových objektů JSON použitím typu JsonNode a dalších typů v System.Text.Json.Nodes oboru názvů. Další informace najdete v části Použití JsonNode.

JsonDocument je IDisposable

JsonDocument vytvoří zobrazení dat v paměti ve sdílené vyrovnávací paměti. Proto na rozdíl od JObject nebo JArray z Newtonsoft.Json typ JsonDocument implementuje IDisposable a je třeba jej 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 zvyšoval výkon a snižoval přidělení paměti pro analýzu běžných velikostí JSON payloadů, tj. < 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ídají JObject, JArray a JToken. Další informace najdete v části Použití JsonNode.

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

Vyhledávání JSON tokenů pomocí JObject nebo JArray z Newtonsoft.Json bývá poměrně rychlé, protože se jedná o vyhledávání ve 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.Utf8JsonReader je vysoce výkonná, s nízkou alokací, jednosměrná čtečka textu JSON kódovaného v UTF-8, čteno z ReadOnlySpan<byte> nebo ReadOnlySequence<byte>. 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 v 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.Json poskytuje rozhraní API, která vrací Nullable<T>, například ReadAsBoolean, která za vás zpracovává NullTokenType a to 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 duplikace zdrojů. 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. Tato obálka by sjednotila veřejné rozhraní 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 odkazem. 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í uzavírat 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í uzavírat 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.

Napište hodnoty časového rozsahu, identifikátoru URI nebo znaku

JsonTextWriter poskytuje WriteValue metody pro TimeSpan, Uri a hodnoty 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 duplikace zdrojů. Jedním ze způsobů, jak sdílet co nejvíce kódu, je vytvořit obálku kolem Utf8JsonWriter a Newtonsoft.Json.JsonTextWriter. Tato obálka by sjednotila veřejné rozhraní 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 funkčnost ekvivalentní ke TypeNameHandling.All z System.Text.Json bylo záměrné. Povolení datové části JSON, aby určovala vlastní informace o typu, je běžným zdrojem zranitelností ve webových aplikacích. Konkrétně konfigurace Newtonsoft.Json a TypeNameHandling.All umožňuje vzdálenému klientovi vložit celou spustitelnou aplikaci do samotné datové části JSON, takže během deserializace webová aplikace extrahuje a spustí vložený kód. Další informace naleznete v dokumentu Pátek třináctého: Útoky JSON na PowerPoint a Pátek třináctého: Podrobnosti o útocích 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 znacích (166 MB) a v kódování base 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. Se System.Text.Json použijte JsonNumberHandling.AllowNamedFloatingPointLiterals. Informace o tom, jak toto nastavení použít, najdete v tématu Povolit nebo napsat čísla v uvozovkách.

Použití AI k migraci

K migraci kódu z Newtonsoft.Json do System.Text.Json v rámci vašeho IDE můžete použít nástroje AI, jako je GitHub Copilot. Výzvu můžete přizpůsobit podle svých požadavků.

Příklad výzvy pro Copilot Chat

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.

Další materiály