Migrera från Newtonsoft.Json till System.Text.Json
Den här artikeln visar hur du migrerar från Newtonsoft.Json till System.Text.Json.
Namnområdet System.Text.Json
innehåller funktioner för serialisering till och deserialisering från JavaScript Object Notation (JSON). Biblioteket System.Text.Json
ingår i körningen för .NET Core 3.1 och senare versioner. Installera NuGet-paketet för System.Text.Json andra målramverk. Paketet stöder:
- .NET Standard 2.0 och senare versioner
- .NET Framework 4.6.2 och senare versioner
- .NET Core 2.0, 2.1 och 2.2
Dricks
Du kan använda AI-hjälp för att migrera från Newtonsoft.Json
med GitHub Copilot.
System.Text.Json
fokuserar främst på prestanda, säkerhet och standardefterlevnad. Den har några viktiga skillnader i standardbeteende och syftar inte till att ha funktionsparitet med Newtonsoft.Json
. För vissa scenarier System.Text.Json
har för närvarande inga inbyggda funktioner, men det finns rekommenderade lösningar. I andra scenarier är lösningar opraktiska.
Teamet System.Text.Json
investerar i att lägga till de funktioner som oftast efterfrågas. Om ditt program är beroende av en funktion som saknas kan du överväga att lämna in ett problem på GitHub-lagringsplatsen dotnet/runtime för att ta reda på om stöd för ditt scenario kan läggas till.
Det mesta av den här artikeln handlar om hur du använder API:et JsonSerializer , men den innehåller även vägledning om hur du använder JsonDocument (som representerar dokumentobjektmodellen eller DOM) Utf8JsonReaderoch Utf8JsonWriter typerna.
I Visual Basic kan du inte använda Utf8JsonReader, vilket också innebär att du inte kan skriva anpassade konverterare. De flesta av de lösningar som presenteras här kräver att du skriver anpassade konverterare. Du kan skriva en anpassad konverterare i C# och registrera den i ett Visual Basic-projekt. Mer information finns i Visual Basic-stöd.
Tabell med skillnader
I följande tabell visas Newtonsoft.Json
funktioner och System.Text.Json
motsvarigheter. Motsvarigheterna delas in i följande kategorier:
- ✔️ Stöds av inbyggda funktioner. Att få liknande beteende från
System.Text.Json
kan kräva användning av ett attribut eller globalt alternativ. - ⚠️ Stöds inte, men det går att lösa problemet. Lösningarna är anpassade konverterare, vilket kanske inte ger fullständig paritet med
Newtonsoft.Json
funktioner. För vissa av dessa tillhandahålls exempelkod som exempel. Om du förlitar dig på de härNewtonsoft.Json
funktionerna kräver migreringen ändringar i .NET-objektmodeller eller andra kodändringar. - ❌ Stöds inte och lösningen är inte praktisk eller möjlig. Om du förlitar dig på dessa
Newtonsoft.Json
funktioner är migrering inte möjlig utan betydande ändringar.
Newtonsoft.Json-funktion | System.Text.Json ekvivalent |
---|---|
Skiftlägesokänslig deserialisering som standard | ✔️ Global inställning för PropertyNameCaseInsensitive |
Namn på kamelfallsegenskap | ✔️ Global inställning för PropertyNamingPolicy |
Ormfallsegenskapsnamn | ✔️ Namngivningsprincip för ormfall |
Minimal teckenundflytning | ✔️ Strikt tecken som flyr, kan konfigureras |
NullValueHandling.Ignore global inställning |
✔️ Global defaultIgnoreCondition-alternativ |
Tillåt kommentarer | ✔️ Global ReadCommentHandling-inställning |
Tillåt avslutande kommatecken | ✔️ Global allowTrailingCommas-inställning |
Registrering av anpassad konverterare | ✔️ Prioritetsordningen skiljer sig åt |
Standard maximalt djup 64, konfigurerbart | ✔️ Standard maximalt djup 64, konfigurerbart |
PreserveReferencesHandling global inställning |
✔️ Global inställning för ReferenceHandling |
Serialisera eller deserialisera tal inom citattecken | ✔️ Global numberhandling-inställning, [JsonNumberHandling]-attribut |
Deserialisera till oföränderliga klasser och structs | ✔️ JsonConstructor, C# 9 Poster |
Stöd för fält | ✔️ Global inställning för IncludeFields, attributet [JsonInclude] |
DefaultValueHandling global inställning |
✔️ Global inställning för DefaultIgnoreCondition |
NullValueHandling inställningen på [JsonProperty] |
✔️ JsonIgnore-attribut |
DefaultValueHandling inställningen på [JsonProperty] |
✔️ JsonIgnore-attribut |
Deserialisera Dictionary med icke-strängnyckel |
✔️ Stödd |
Stöd för icke-offentliga fastighetssättare och getters | ✔️ JsonInclude-attribut |
[JsonConstructor] -attribut |
✔️ [JsonConstructor]-attribut |
ReferenceLoopHandling global inställning |
✔️ Global inställning för ReferenceHandling |
Återanrop | ✔️ Callbacks |
NaN, Infinity, -Infinity | ✔️ Stödd |
Required inställning för [JsonProperty] attribut |
✔️ [JsonRequired] attribut och C# krävs modifierare |
DefaultContractResolver för att ignorera egenskaper |
✔️ DefaultJsonTypeInfoResolver-klass |
Polymorf serialisering | ✔️ [JsonDerivedType]-attribut |
Polymorf deserialisering | ✔️ Skriv diskriminerande på attributet [JsonDerivedType] |
Deserialisera stränguppräkningsvärde | ✔️ Deserialisera stränguppräkningsvärden |
MissingMemberHandling global inställning |
✔️ Hantera saknade medlemmar |
Fyll i egenskaper utan setters | ✔️ Fyll i egenskaper utan setters |
ObjectCreationHandling global inställning |
✔️ Återanvänd i stället för att ersätta egenskaper |
Stöd för ett brett spektrum av typer | ⚠️ Vissa typer kräver anpassade konverterare |
Deserialisera uppskjuten typ till object egenskaper |
⚠️ Stöds inte, lösning, exempel |
Deserialisera JSON-literal null till värdetyper som inte kan nulliseras |
⚠️ Stöds inte, lösning, exempel |
DateTimeZoneHandling , DateFormatString inställningar |
⚠️ Stöds inte, lösning, exempel |
JsonConvert.PopulateObject metod |
⚠️ Stöds inte, lösning |
Stöd för System.Runtime.Serialization attribut |
⚠️ Stöds inte, lösning, exempel |
JsonObjectAttribute |
⚠️ Stöds inte, lösning |
Tillåt egenskapsnamn utan citattecken | ❌Stöds inte av design |
Tillåt enkla citattecken runt strängvärden | ❌Stöds inte av design |
Tillåt JSON-värden som inte är strängar för strängegenskaper | ❌Stöds inte av design |
TypeNameHandling.All global inställning |
❌Stöds inte av design |
Stöd för JsonPath frågor |
❌Stöds ej |
Konfigurerbara gränser | ❌Stöds ej |
Newtonsoft.Json-funktion | System.Text.Json ekvivalent |
---|---|
Skiftlägesokänslig deserialisering som standard | ✔️ Global inställning för PropertyNameCaseInsensitive |
Namn på kamelfallsegenskap | ✔️ Global inställning för PropertyNamingPolicy |
Minimal teckenundflytning | ✔️ Strikt tecken som flyr, kan konfigureras |
NullValueHandling.Ignore global inställning |
✔️ Global defaultIgnoreCondition-alternativ |
Tillåt kommentarer | ✔️ Global ReadCommentHandling-inställning |
Tillåt avslutande kommatecken | ✔️ Global allowTrailingCommas-inställning |
Registrering av anpassad konverterare | ✔️ Prioritetsordningen skiljer sig åt |
Standard maximalt djup 64, konfigurerbart | ✔️ Standard maximalt djup 64, konfigurerbart |
PreserveReferencesHandling global inställning |
✔️ Global inställning för ReferenceHandling |
Serialisera eller deserialisera tal inom citattecken | ✔️ Global numberhandling-inställning, [JsonNumberHandling]-attribut |
Deserialisera till oföränderliga klasser och structs | ✔️ JsonConstructor, C# 9 Poster |
Stöd för fält | ✔️ Global inställning för IncludeFields, attributet [JsonInclude] |
DefaultValueHandling global inställning |
✔️ Global inställning för DefaultIgnoreCondition |
NullValueHandling inställningen på [JsonProperty] |
✔️ JsonIgnore-attribut |
DefaultValueHandling inställningen på [JsonProperty] |
✔️ JsonIgnore-attribut |
Deserialisera Dictionary med icke-strängnyckel |
✔️ Stödd |
Stöd för icke-offentliga fastighetssättare och getters | ✔️ JsonInclude-attribut |
[JsonConstructor] -attribut |
✔️ [JsonConstructor]-attribut |
ReferenceLoopHandling global inställning |
✔️ Global inställning för ReferenceHandling |
Återanrop | ✔️ Callbacks |
NaN, Infinity, -Infinity | ✔️ Stödd |
Required inställning för [JsonProperty] attribut |
✔️ [JsonRequired] attribut och C# krävs modifierare |
DefaultContractResolver för att ignorera egenskaper |
✔️ DefaultJsonTypeInfoResolver-klass |
Polymorf serialisering | ✔️ [JsonDerivedType]-attribut |
Polymorf deserialisering | ✔️ Skriv diskriminerande på attributet [JsonDerivedType] |
Deserialisera stränguppräkningsvärde | ✔️ Deserialisera stränguppräkningsvärden |
Stöd för ett brett spektrum av typer | ⚠️ Vissa typer kräver anpassade konverterare |
Deserialisera uppskjuten typ till object egenskaper |
⚠️ Stöds inte, lösning, exempel |
Deserialisera JSON-literal null till värdetyper som inte kan nulliseras |
⚠️ Stöds inte, lösning, exempel |
DateTimeZoneHandling , DateFormatString inställningar |
⚠️ Stöds inte, lösning, exempel |
JsonConvert.PopulateObject metod |
⚠️ Stöds inte, lösning |
ObjectCreationHandling global inställning |
⚠️ Stöds inte, lösning |
Lägg till i samlingar utan set | ⚠️ Stöds inte, lösning |
Ormfallsegenskapsnamn | ⚠️ Stöds inte, lösning |
Stöd för System.Runtime.Serialization attribut |
⚠️ Stöds inte, lösning, exempel |
MissingMemberHandling global inställning |
⚠️ Stöds inte, lösning, exempel |
JsonObjectAttribute |
⚠️ Stöds inte, lösning |
Tillåt egenskapsnamn utan citattecken | ❌Stöds inte av design |
Tillåt enkla citattecken runt strängvärden | ❌Stöds inte av design |
Tillåt JSON-värden som inte är strängar för strängegenskaper | ❌Stöds inte av design |
TypeNameHandling.All global inställning |
❌Stöds inte av design |
Stöd för JsonPath frågor |
❌Stöds ej |
Konfigurerbara gränser | ❌Stöds ej |
Newtonsoft.Json-funktion | System.Text.Json ekvivalent |
---|---|
Skiftlägesokänslig deserialisering som standard | ✔️ Global inställning för PropertyNameCaseInsensitive |
Namn på kamelfallsegenskap | ✔️ Global inställning för PropertyNamingPolicy |
Minimal teckenundflytning | ✔️ Strikt tecken som flyr, kan konfigureras |
NullValueHandling.Ignore global inställning |
✔️ Global defaultIgnoreCondition-alternativ |
Tillåt kommentarer | ✔️ Global ReadCommentHandling-inställning |
Tillåt avslutande kommatecken | ✔️ Global allowTrailingCommas-inställning |
Registrering av anpassad konverterare | ✔️ Prioritetsordningen skiljer sig åt |
Standard maximalt djup 64, konfigurerbart | ✔️ Standard maximalt djup 64, konfigurerbart |
PreserveReferencesHandling global inställning |
✔️ Global inställning för ReferenceHandling |
Serialisera eller deserialisera tal inom citattecken | ✔️ Global numberhandling-inställning, [JsonNumberHandling]-attribut |
Deserialisera till oföränderliga klasser och structs | ✔️ JsonConstructor, C# 9 Poster |
Stöd för fält | ✔️ Global inställning för IncludeFields, attributet [JsonInclude] |
DefaultValueHandling global inställning |
✔️ Global inställning för DefaultIgnoreCondition |
NullValueHandling inställningen på [JsonProperty] |
✔️ JsonIgnore-attribut |
DefaultValueHandling inställningen på [JsonProperty] |
✔️ JsonIgnore-attribut |
Deserialisera Dictionary med icke-strängnyckel |
✔️ Stödd |
Stöd för icke-offentliga fastighetssättare och getters | ✔️ JsonInclude-attribut |
[JsonConstructor] -attribut |
✔️ [JsonConstructor]-attribut |
ReferenceLoopHandling global inställning |
✔️ Global inställning för ReferenceHandling |
Återanrop | ✔️ Callbacks |
NaN, Infinity, -Infinity | ✔️ Stödd |
Deserialisera stränguppräkningsvärde | ✔️ Deserialisera stränguppräkningsvärden |
Stöd för ett brett spektrum av typer | ⚠️ Vissa typer kräver anpassade konverterare |
Polymorf serialisering | ⚠️ Stöds inte, lösning, exempel |
Polymorf deserialisering | ⚠️ Stöds inte, lösning, exempel |
Deserialisera uppskjuten typ till object egenskaper |
⚠️ Stöds inte, lösning, exempel |
Deserialisera JSON-literal null till värdetyper som inte kan nulliseras |
⚠️ Stöds inte, lösning, exempel |
Required inställning för [JsonProperty] attribut |
⚠️ Stöds inte, lösning, exempel |
DefaultContractResolver för att ignorera egenskaper |
⚠️ Stöds inte, lösning, exempel |
DateTimeZoneHandling , DateFormatString inställningar |
⚠️ Stöds inte, lösning, exempel |
JsonConvert.PopulateObject metod |
⚠️ Stöds inte, lösning |
ObjectCreationHandling global inställning |
⚠️ Stöds inte, lösning |
Lägg till i samlingar utan set | ⚠️ Stöds inte, lösning |
Ormfallsegenskapsnamn | ⚠️ Stöds inte, lösning |
JsonObjectAttribute |
⚠️ Stöds inte, lösning |
Stöd för System.Runtime.Serialization attribut |
❌Stöds ej |
MissingMemberHandling global inställning |
❌Stöds ej |
Tillåt egenskapsnamn utan citattecken | ❌Stöds inte av design |
Tillåt enkla citattecken runt strängvärden | ❌Stöds inte av design |
Tillåt JSON-värden som inte är strängar för strängegenskaper | ❌Stöds inte av design |
TypeNameHandling.All global inställning |
❌Stöds inte av design |
Stöd för JsonPath frågor |
❌Stöds ej |
Konfigurerbara gränser | ❌Stöds ej |
Det här är inte en fullständig lista över Newtonsoft.Json
funktioner. Listan innehåller många av de scenarier som har begärts i GitHub-problem eller StackOverflow-inlägg . Om du implementerar en lösning för ett av scenarierna som visas här som för närvarande inte har exempelkod, och om du vill dela din lösning väljer du Den här sidan i avsnittet Feedback längst ned på den här sidan. Det skapar ett problem i den här dokumentationens GitHub-lagringsplats och listar det i avsnittet Feedback på den här sidan också.
Skillnader i standardbeteende
System.Text.Json är strikt som standard och undviker alla gissningar eller tolkningar för anroparens räkning, med betoning på deterministiskt beteende. Biblioteket är avsiktligt utformat på det här sättet för prestanda och säkerhet. Newtonsoft.Json
är flexibel som standard. Den här grundläggande skillnaden i design ligger bakom många av följande specifika skillnader i standardbeteende.
Skiftlägesokänslig deserialisering
Under deserialiseringen Newtonsoft.Json
matchar skiftlägesokänsliga egenskapsnamn som standard. Standardvärdet System.Text.Json är skiftlägeskänsligt, vilket ger bättre prestanda eftersom det gör en exakt matchning. Information om hur du gör skiftlägesokänslig matchning finns i Skiftlägesokänslig egenskapsmatchning.
Om du använder System.Text.Json
indirekt med hjälp av ASP.NET Core behöver du inte göra något för att få beteende som Newtonsoft.Json
. ASP.NET Core anger inställningarna för kamel-casing egenskapsnamn och skiftlägesokänslig matchning när den använder System.Text.Json
.
ASP.NET Core möjliggör också deserialisering av citerade tal som standard.
Minimal teckenundflytning
Under serialiseringen Newtonsoft.Json
är det relativt tillåtande att släppa igenom tecken utan att ta bort dem. Det innebär att den inte ersätter dem med \uxxxx
var xxxx
är tecknets kodpunkt. Om det inte undfly dem, gör det genom att sända en \
före tecknet (till exempel "
blir \"
). System.Text.Json undflyr som standard fler tecken för att ge skydd på djupet mot XSS-attacker (cross-site scripting) eller informationsupplysning och gör det med hjälp av sekvensen med sex tecken. System.Text.Json
undflyr alla icke-ASCII-tecken som standard, så du behöver inte göra något om du använder StringEscapeHandling.EscapeNonAscii
i Newtonsoft.Json
. System.Text.Json
undflyr också HTML-känsliga tecken som standard. Information om hur du åsidosätter standardbeteendet System.Text.Json
finns i Anpassa teckenkodning.
Kommentarer
Under deserialiseringen Newtonsoft.Json
ignorerar kommentarer i JSON som standard. Standardvärdet System.Text.Json är att utlösa undantag för kommentarer eftersom RFC 8259-specifikationen inte innehåller dem. Information om hur du tillåter kommentarer finns i Tillåt kommentarer och avslutande kommatecken.
Avslutande kommatecken
Under deserialiseringen Newtonsoft.Json
ignorerar efterföljande kommatecken som standard. Den ignorerar också flera avslutande kommatecken (till exempel [{"Color":"Red"},{"Color":"Green"},,]
). Standardvärdet System.Text.Json är att utlösa undantag för avslutande kommatecken eftersom RFC 8259-specifikationen inte tillåter dem. Information om hur du godkänner System.Text.Json
dem finns i Tillåt kommentarer och avslutande kommatecken. Det finns inget sätt att tillåta flera avslutande kommatecken.
Registreringspriorence för konverterare
Registreringspriorensen Newtonsoft.Json
för anpassade konverterare är följande:
- Attribut för egenskapen
- Attribut på typ
- Konverterarsamling
Den här ordningen innebär att en anpassad konverterare i Converters
samlingen åsidosätts av en konverterare som registreras genom att ett attribut tillämpas på typnivå. Båda dessa registreringar åsidosättas av ett attribut på egenskapsnivå.
Registreringspriorensen System.Text.Json för anpassade konverterare skiljer sig:
- Attribut för egenskapen
- Converters samling
- Attribut på typ
Skillnaden här är att en anpassad konverterare i Converters
samlingen åsidosätter ett attribut på typnivå. Avsikten med den här prioritetsordningen är att göra körningsändringar åsidosätter val av designtid. Det finns inget sätt att ändra prioriteten.
Mer information om registrering av anpassade konverterare finns i Registrera en anpassad konverterare.
Maximalt djup
Den senaste versionen av Newtonsoft.Json
har en maximal djupgräns på 64 som standard. System.Text.Json har också en standardgräns på 64 och kan konfigureras genom att ange JsonSerializerOptions.MaxDepth.
Om du använder System.Text.Json
indirekt med hjälp av ASP.NET Core är standardgränsen för maximalt djup 32. Standardvärdet är samma som för modellbindning och anges i klassen JsonOptions.
JSON-strängar (egenskapsnamn och strängvärden)
Under deserialiseringen Newtonsoft.Json
accepterar egenskapsnamn omgivna av dubbla citattecken, enkla citattecken eller utan citattecken. Den accepterar strängvärden som omges av dubbla citattecken eller enkla citattecken. Accepterar till exempel Newtonsoft.Json
följande JSON:
{
"name1": "value",
'name2': "value",
name3: 'value'
}
System.Text.Json
accepterar endast egenskapsnamn och strängvärden inom dubbla citattecken eftersom formatet krävs av RFC 8259-specifikationen och är det enda format som anses vara giltigt JSON.
Ett värde som omges av enkla citattecken resulterar i en JsonException med följande meddelande:
''' is an invalid start of a value.
Värden som inte är strängvärden för strängegenskaper
Newtonsoft.Json
accepterar icke-strängvärden, till exempel ett tal eller literaler true
och false
, för deserialisering till egenskaper av typen sträng. Här är ett exempel på JSON som Newtonsoft.Json
deserialiserar till följande klass:
{
"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
deserialiserar inte icke-strängvärden till strängegenskaper. Ett icke-strängvärde som tas emot för ett strängfält resulterar i en JsonException med följande meddelande:
The JSON value could not be converted to System.String.
Scenarier med JsonSerializer
Några av följande scenarier stöds inte av inbyggda funktioner, men det är möjligt med lösningar. Lösningarna är anpassade konverterare, vilket kanske inte ger fullständig paritet med Newtonsoft.Json
funktioner. För vissa av dessa tillhandahålls exempelkod som exempel. Om du förlitar dig på de här Newtonsoft.Json
funktionerna kräver migreringen ändringar i .NET-objektmodeller eller andra kodändringar.
För några av följande scenarier är lösningar inte praktiska eller möjliga. Om du förlitar dig på dessa Newtonsoft.Json
funktioner är migrering inte möjlig utan betydande ändringar.
Tillåt eller skriva tal inom citattecken
Newtonsoft.Json
kan serialisera eller deserialisera tal som representeras av JSON-strängar (omgivna av citattecken). Den kan till exempel acceptera: {"DegreesCelsius":"23"}
i stället {"DegreesCelsius":23}
för . Om du vill aktivera det beteendet i System.Text.Jsonanger du JsonSerializerOptions.NumberHandling till WriteAsString eller AllowReadingFromStringeller använder attributet [JsonNumberHandling].
Om du använder System.Text.Json
indirekt med hjälp av ASP.NET Core behöver du inte göra något för att få beteende som Newtonsoft.Json
. ASP.NET Core anger webbstandarder när den använder System.Text.Json
, och webbstandarder tillåter citerade tal.
Mer information finns i Tillåt eller skriva tal inom citattecken.
Ange konstruktor som ska användas vid deserialisering
Med Newtonsoft.Json
[JsonConstructor]
attributet kan du ange vilken konstruktor som ska anropas vid deserialisering till en POCO.
System.Text.Json
har också ett [JsonConstructor]- attribut. Mer information finns i Oföränderliga typer och poster.
Ignorera en egenskap villkorligt
Newtonsoft.Json
har flera sätt att villkorligt ignorera en egenskap för serialisering eller deserialisering:
DefaultContractResolver
låter dig välja egenskaper som ska inkluderas eller ignoreras baserat på godtyckliga kriterier.- Med
NullValueHandling
inställningarna ochDefaultValueHandling
påJsonSerializerSettings
kan du ange att alla null-värde- eller standardvärdeegenskaper ska ignoreras. - Med
NullValueHandling
inställningarna ochDefaultValueHandling
för[JsonProperty]
attributet kan du ange enskilda egenskaper som ska ignoreras när värdet är null eller standardvärdet.
System.Text.Json tillhandahåller följande sätt att ignorera egenskaper eller fält vid serialisering:
- Attributet [JsonIgnore] på en egenskap gör att egenskapen utelämnas från JSON under serialiseringen.
- Med alternativet IgnoreReadOnlyProperties global kan du ignorera alla skrivskyddade egenskaper.
- Om du inkluderar fält kan du med det JsonSerializerOptions.IgnoreReadOnlyFields globala alternativet ignorera alla skrivskyddade fält.
- Med
DefaultIgnoreCondition
det globala alternativet kan du ignorera alla värdetypsegenskaper som har standardvärden eller ignorera alla referenstypsegenskaper som har null-värden.
I .NET 7 och senare versioner kan du dessutom anpassa JSON-kontraktet för att ignorera egenskaper baserat på godtyckliga kriterier. Mer information finns i Anpassade kontrakt.
Med de här alternativen kan du inte ignorera valda egenskaper baserat på godtyckliga kriterier som utvärderas vid körning.
Offentliga och icke-offentliga fält
Newtonsoft.Json
kan serialisera och deserialisera fält samt egenskaper.
I System.Text.Jsonanvänder du den JsonSerializerOptions.IncludeFields globala inställningen eller attributet [JsonInclude] för att inkludera offentliga fält vid serialisering eller deserialisering. Ett exempel finns i Inkludera fält.
Bevara objektreferenser och referensloopar
Som standard Newtonsoft.Json
serialiserar efter värde. Om ett objekt till exempel innehåller två egenskaper som innehåller en referens till samma Person
objekt dupliceras värdena Person
för objektets egenskaper i JSON.
Newtonsoft.Json
har en PreserveReferencesHandling
inställning på JsonSerializerSettings
som gör att du kan serialisera med referens:
- En identifierarmetadata läggs till i den JSON som skapades för det första
Person
objektet. - JSON som skapas för det andra
Person
objektet innehåller en referens till identifieraren i stället för egenskapsvärden.
Newtonsoft.Json
har också en ReferenceLoopHandling
inställning som gör att du kan ignorera cirkelreferenser i stället för att utlösa ett undantag.
Om du vill bevara referenser och hantera cirkelreferenser i System.Text.Jsonanger du JsonSerializerOptions.ReferenceHandler till Preserve. Inställningen ReferenceHandler.Preserve
motsvararPreserveReferencesHandling.All
PreserveReferencesHandling
= i .Newtonsoft.Json
Alternativet ReferenceHandler.IgnoreCycles
har ett beteende som liknar Newtonsoft.JsonReferenceLoopHandling.Ignore
. En skillnad är att implementeringen System.Text.Json ersätter referensslingor med null
JSON-token i stället för att ignorera objektreferensen. Mer information finns i Ignorera cirkelreferenser.
Newtonsoft.JsonPrecis som ReferenceResolverSystem.Text.Json.Serialization.ReferenceResolver definierar klassen beteendet att bevara referenser för serialisering och deserialisering. Skapa en härledd klass för att ange anpassat beteende. Ett exempel finns i GuidReferenceResolver.
Vissa relaterade Newtonsoft.Json
funktioner stöds inte:
Mer information finns i Bevara referenser och hantera cirkelreferenser.
Ordlista med icke-strängnyckel
Både Newtonsoft.Json
och System.Text.Json
stöder samlingar av typen Dictionary<TKey, TValue>
. I måste dock System.Text.Json
TKey
vara en primitiv typ, inte en anpassad typ. Mer information finns i Nyckeltyper som stöds.
Varning
Deserialisera till en Dictionary<TKey, TValue>
plats där TKey
skrivs som något annat än string
kan medföra en säkerhetsrisk i det förbrukande programmet. Mer information finns i dotnet/runtime#4761.
Typer utan inbyggt stöd
System.Text.Json ger inte inbyggt stöd för följande typer:
- DataTable och relaterade typer (mer information finns i Samlingstyper som stöds)
- ExpandoObject
- TimeZoneInfo
- BigInteger
- DBNull
- Type
- ValueTuple och dess associerade generiska typer
Anpassade konverterare kan implementeras för typer som inte har inbyggt stöd.
Polymorf serialisering
Newtonsoft.Json
utför automatiskt polymorf serialisering. Från och med .NET 7 System.Text.Json stöder polymorf serialisering via attributet JsonDerivedTypeAttribute . Mer information finns i Serialisera egenskaper för härledda klasser.
Polymorf deserialisering
Newtonsoft.Json
har en TypeNameHandling
inställning som lägger till typnamnsmetadata till JSON vid serialisering. Den använder metadata vid deserialisering för att utföra polymorfialisering. Från och med .NET 7 System.Text.Json förlitar sig på typdiskriminerande information för att utföra polymorf deserialisering. Dessa metadata genereras i JSON och används sedan under deserialiseringen för att avgöra om deserialisera till bastypen eller en härledd typ. Mer information finns i Serialisera egenskaper för härledda klasser.
Om du vill stödja polymorf deserialisering i äldre .NET-versioner skapar du en konverterare som exemplet i Så här skriver du anpassade konverterare.
Deserialisera stränguppräkningsvärden
Som standard System.Text.Json stöder inte deserialisering av stränguppräkningsvärden, medan Newtonsoft.Json
det gör det. Följande kod genererar till exempel en 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
}
Du kan dock aktivera deserialisering av stränguppräkningsvärden med hjälp JsonStringEnumConverter av konverteraren. Mer information finns i Räkna upp som strängar.
Deserialisering av objektegenskaper
När Newtonsoft.Json
deserialiserar till Object, det:
- Härleder typen av primitiva värden i JSON-nyttolasten (förutom
null
) och returnerar lagradestring
,long
,double
,boolean
ellerDateTime
som ett rutat objekt. Primitiva värden är enkla JSON-värden, till exempel ett JSON-tal, en sträng,true
,false
ellernull
. - Returnerar ett
JObject
ellerJArray
för komplexa värden i JSON-nyttolasten. Komplexa värden är samlingar av JSON-nyckel/värde-par inom klammerparenteser ({}
) eller listor med värden inom hakparenteser ([]
). Egenskaper och värden inom klammerparenteser eller hakparenteser kan ha ytterligare egenskaper eller värden. - Returnerar en null-referens när nyttolasten har JSON-literalen
null
.
System.Text.Json lagrar en ruta JsonElement
för både primitiva och komplexa värden när deserialisera till , till Objectexempel:
- En
object
egenskap. - Ett
object
ordlistevärde. - Ett
object
matrisvärde. - En rot
object
.
Behandlar null
dock System.Text.Json
samma som Newtonsoft.Json
och returnerar en null-referens när nyttolasten har JSON-literalen null
i sig.
Om du vill implementera typinferens för object
egenskaper skapar du en konverterare som exemplet i Så här skriver du anpassade konverterare.
Deserialisera null till icke-nullbar typ
Newtonsoft.Json
utlöser inget undantag i följande scenario:
NullValueHandling
är inställt påIgnore
, och- Under deserialiseringen innehåller JSON ett null-värde för en värdetyp som inte kan nulliseras.
I samma scenario utlöser System.Text.Json ett undantag. (Motsvarande null-hanteringsinställning i System.Text.Json
är JsonSerializerOptions.IgnoreNullValues = true
.)
Om du äger måltypen är den bästa lösningen att göra egenskapen i fråga nullbar (till exempel ändra int
till int?
).
En annan lösning är att skapa en konverterare för typen, till exempel följande exempel som hanterar null-värden för DateTimeOffset
typer:
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);
}
}
Registrera den här anpassade konverteraren med hjälp av ett attribut på egenskapen eller genom att lägga till konverteraren i Converters samlingen.
Obs! Den föregående konverteraren hanterar null-värden på ett annat sätt än Newtonsoft.Json
för POCO:er som anger standardvärden. Anta till exempel att följande kod representerar målobjektet:
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; }
}
Och anta att följande JSON deserialiseras med hjälp av föregående konverterare:
{
"Date": null,
"TemperatureCelsius": 25,
"Summary": null
}
Efter deserialiseringen Date
har egenskapen 1/1/0001 (default(DateTimeOffset)
), dvs. värdet som anges i konstruktorn skrivs över. Med samma POCO och JSON Newtonsoft.Json
skulle deserialisering lämna 1/1/2001 i egenskapen Date
.
Deserialisera till oföränderliga klasser och structs
Newtonsoft.Json
kan deserialisera till oföränderliga klasser och structs eftersom den kan använda konstruktorer som har parametrar.
I System.Text.Jsonanvänder du attributet [JsonConstructor] för att ange användning av en parameteriserad konstruktor. Poster i C# 9 är också oföränderliga och stöds som deserialiseringsmål. Mer information finns i Oföränderliga typer och poster.
Nödvändiga egenskaper
I Newtonsoft.Json
anger du att en egenskap krävs genom att ange Required
attributet [JsonProperty]
. Newtonsoft.Json
genererar ett undantag om inget värde tas emot i JSON för en egenskap som har markerats som obligatorisk.
Från och med .NET 7 kan du använda C# required
-modifieraren eller JsonRequiredAttribute attributet på en obligatorisk egenskap. System.Text.Json genererar ett undantag om JSON-nyttolasten inte innehåller något värde för den markerade egenskapen. Mer information finns i Obligatoriska egenskaper.
System.Text.Json utlöser inte ett undantag om inget värde tas emot för någon av egenskaperna för måltypen. Om du till exempel har en WeatherForecast
klass:
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
Följande JSON deserialiseras utan fel:
{
"TemperatureCelsius": 25,
"Summary": "Hot"
}
Om du vill att deserialiseringen ska misslyckas om ingen Date
egenskap finns i JSON väljer du något av följande alternativ:
- Använd .NET 7- eller senare-versionen av System.Text.Json paketet och lägg till
required
modifieraren (tillgänglig från och med C# 11) eller JsonRequiredAttribute attributet till egenskapen. - Implementera en anpassad konverterare.
- Implementera ett
OnDeserialized
återanrop (.NET 6 och senare).
Följande exempelkonverterare utlöser ett undantag om Date
egenskapen inte har angetts när deserialiseringen är klar:
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);
}
}
}
Registrera den här anpassade konverteraren genom att lägga till konverteraren i JsonSerializerOptions.Converters samlingen.
Det här mönstret för att rekursivt anropa konverteraren kräver att du registrerar konverteraren med hjälp JsonSerializerOptionsav , inte med hjälp av ett attribut. Om du registrerar konverteraren med hjälp av ett attribut anropar den anpassade konverteraren rekursivt till sig själv. Resultatet är en oändlig loop som slutar i ett stacköverflödesfel.
När du registrerar konverteraren med hjälp av alternativobjektet undviker du en oändlig loop genom att inte skicka in alternativobjektet när du rekursivt anropar Serialize eller Deserialize. Alternativobjektet innehåller Converters samlingen. Om du skickar in den till Serialize
eller Deserialize
anropar den anpassade konverteraren till sig själv, vilket gör en oändlig loop som resulterar i ett stacköverflödesfel. Om standardalternativen inte är möjliga skapar du en ny instans av alternativen med de inställningar som du behöver. Den här metoden går långsamt eftersom varje ny instans cachelagrar oberoende av varandra.
Det finns ett alternativt mönster som kan använda JsonConverterAttribute
registrering i klassen för att konverteras. I den här metoden anropar Serialize
konverterarkoden eller Deserialize
på en klass som härleds från klassen som ska konverteras. Den härledda klassen har ingen tillämpad JsonConverterAttribute
på den. I följande exempel på det här alternativet:
WeatherForecastWithRequiredPropertyConverterAttribute
är klassen som ska deserialiseras och har tillämpatsJsonConverterAttribute
på den.WeatherForecastWithoutRequiredPropertyConverterAttribute
är den härledda klassen som inte har konverterarattributet.- Koden i konverteraren anropar
Serialize
ochDeserialize
påWeatherForecastWithoutRequiredPropertyConverterAttribute
för att undvika en oändlig loop. Det finns en prestandakostnad för den här metoden för serialisering på grund av en extra objekt-instansiering och kopiering av egenskapsvärden.
Här är typerna WeatherForecast*
:
[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
{
}
Och här är konverteraren:
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);
}
}
}
Den obligatoriska egenskapskonverteraren skulle kräva ytterligare logik om du behöver hantera attribut som [JsonIgnore] eller olika alternativ, till exempel anpassade kodare. Exempelkoden hanterar inte heller egenskaper för vilka ett standardvärde anges i konstruktorn. Och den här metoden skiljer inte mellan följande scenarier:
- En egenskap saknas i JSON.
- En egenskap för en icke-nullbar typ finns i JSON, men värdet är standardvärdet för typen, till exempel noll för en
int
. - En egenskap för en nullbar värdetyp finns i JSON, men värdet är null.
Kommentar
Om du använder System.Text.Json från en ASP.NET Core-styrenhet kanske du kan använda ett [Required]
attribut för egenskaperna för modellklassen i stället för att implementera en System.Text.Json konverterare.
Ange datumformat
Newtonsoft.Json
innehåller flera sätt att styra hur egenskaper DateTime
för och DateTimeOffset
typer serialiseras och deserialiseras:
- Inställningen
DateTimeZoneHandling
kan användas för att serialisera allaDateTime
värden som UTC-datum. - Inställningen
DateFormatString
ochDateTime
konverterarna kan användas för att anpassa formatet för datumsträngar.
System.Text.Json stöder ISO 8601-1:2019, inklusive RFC 3339-profilen. Det här formatet är allmänt antaget, entydigt och gör tur och retur just. Om du vill använda andra format skapar du en anpassad konverterare. Till exempel serialiserar och deserialiserar följande konverterare JSON som använder Unix-epokformat med eller utan en tidszonsförskjutning (värden som /Date(1590863400000-0700)/
eller /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);
}
}
Mer information finns i Stöd för DateTime och DateTimeOffset i System.Text.Json.
Återanrop
Newtonsoft.Json
låter dig köra anpassad kod på flera punkter i serialiserings- eller deserialiseringsprocessen:
- OnDeserializing (när du börjar deserialisera ett objekt)
- OnDeserialized (när det är klart att deserialisera ett objekt)
- OnSerializing (när du börjar serialisera ett objekt)
- OnSerialized (när du är klar med serialiseringen av ett objekt)
System.Text.Json exponerar samma meddelanden under serialisering och deserialisering. Om du vill använda dem implementerar du ett eller flera av följande gränssnitt från System.Text.Json.Serialization namnområdet:
Här är ett exempel som söker efter en null-egenskap och skriver meddelanden i början och slutet av serialisering och deserialisering:
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=
Koden OnDeserializing
har inte åtkomst till den nya POCO-instansen. Om du vill ändra den nya POCO-instansen i början av deserialiseringen placerar du koden i POCO-konstruktorn.
Icke-offentliga fastighetssättare och getters
Newtonsoft.Json
kan använda privata och interna egenskapsuppsättningar och getters via attributet JsonProperty
.
System.Text.Jsonstöder privata och interna egenskapsuppsättningar och getters via attributet [JsonInclude]. Exempelkod finns i Icke-offentliga egenskapsåtkomster.
Fylla i befintliga objekt
Metoden JsonConvert.PopulateObject
i Newtonsoft.Json
deserialiserar ett JSON-dokument till en befintlig instans av en klass, i stället för att skapa en ny instans. System.Text.Json skapar alltid en ny instans av måltypen med hjälp av standardkonstruktorn utan offentliga parametrar. Anpassade konverterare kan deserialisera till en befintlig instans.
Återanvänd i stället för att ersätta egenskaper
Från och med .NET 8 System.Text.Json har stöd för återanvändning av initierade egenskaper i stället för att ersätta dem. Det finns vissa skillnader i beteende som du kan läsa om i API-förslaget.
Mer information finns i Fyll i initierade egenskaper.
Med ObjectCreationHandling
inställningen i Newtonsoft.Json
kan du ange att objekt i egenskaper ska återanvändas i stället för att ersättas under deserialisering. System.Text.Json ersätter alltid objekt i egenskaper. Anpassade konverterare kan tillhandahålla den här funktionen, eller så kan du uppgradera till .NET 8, vilket ger fyllnadsfunktioner.
Fyll i egenskaper utan setters
Från och med .NET 8 System.Text.Json har stöd för att fylla i egenskaper, inklusive de som inte har en setter. Mer information finns i Fyll i initierade egenskaper.
Under deserialiseringen Newtonsoft.Json
lägger du till objekt i en samling även om egenskapen inte har någon setter. System.Text.Json ignorerar egenskaper som inte har setters. Anpassade konverterare kan tillhandahålla den här funktionen, eller så kan du uppgradera till .NET 8, som kan fylla i skrivskyddade egenskaper.
Namngivningsprincip för ormfall
System.Text.Json innehåller en inbyggd namngivningsprincip för ormfall. Det finns dock vissa beteendeskillnader med Newtonsoft.Json
för vissa indata. I följande tabell visas några av dessa skillnader när du konverterar indata med hjälp av JsonNamingPolicy.SnakeCaseLower principen.
Indata | Newtonsoft.Json resultat | System.Text.Json resultat |
---|---|---|
"AB1" | "a_b1" | "ab1" |
"SHA512Managed" | "sh_a512_managed" | "sha512_managed" |
"abc123DEF456" | "abc123_de_f456" | "abc123_def456" |
"KEBAB-CASE" | "keba_b-_case" | "kebab-case" |
Den enda inbyggda namngivningsprincipen för egenskaper i System.Text.Json är för kamelfall. Newtonsoft.Json
kan konvertera egenskapsnamn till ormfall. En anpassad namngivningsprincip kan tillhandahålla den här funktionen eller uppgradera till .NET 8 eller senare, vilket inkluderar inbyggda namngivningsprinciper för ormfall.
System.Runtime.Serialization-attribut
System.Runtime.Serialization attribut som DataContractAttribute, DataMemberAttributeoch IgnoreDataMemberAttribute låter dig definiera ett datakontrakt. Ett datakontrakt är ett formellt avtal mellan en tjänst och en klient som abstrakt beskriver de data som ska utbytas. Datakontraktet definierar exakt vilka egenskaper som serialiseras för utbyte.
System.Text.Json har inte inbyggt stöd för dessa attribut. Från och med .NET 7 kan du dock använda en anpassad typlösare för att lägga till stöd. Ett exempel finns i ZCS. DataContractResolver.
Oktalnummer
Newtonsoft.Json
behandlar tal med inledande nolla som oktala tal. System.Text.Jsontillåter inte inledande nolla eftersom RFC 8259-specifikationen inte tillåter dem.
Hantera saknade medlemmar
Om den JSON som deserialiseras innehåller egenskaper som saknas i måltypen kan Newtonsoft.Json
konfigureras för att utlösa undantag. Som standard System.Text.Json ignorerar extra egenskaper i JSON, förutom när du använder attributet [JsonExtensionData].
I .NET 8 och senare versioner kan du ange om du vill hoppa över eller inte tillåta ommappade JSON-egenskaper med något av följande sätt:
- JsonUnmappedMemberHandlingAttribute Använd attributet för den typ som du deserialiserar på.
- Ange egenskapen för JsonSerializerOptions.UnmappedMemberHandling att ange din inställning globalt. Eller för källgenerering anger JsonSourceGenerationOptionsAttribute.UnmappedMemberHandling du egenskapen och tillämpar attributet på din JsonSerializerContext klass.
- Anpassa egenskapen JsonTypeInfo.UnmappedMemberHandling .
JsonObjectAttribute
Newtonsoft.Json
har ett attribut, JsonObjectAttribute
, som kan tillämpas på typnivå för att styra vilka medlemmar som serialiseras, hur null
värden hanteras och om alla medlemmar krävs. System.Text.Json har inget motsvarande attribut som kan tillämpas på en typ. För vissa beteenden, till exempel null
värdehantering, kan du antingen konfigurera samma beteende på den globala JsonSerializerOptions eller individuellt för varje egenskap.
Tänk på följande exempel som används Newtonsoft.Json.JsonObjectAttribute
för att ange att alla null
egenskaper ska ignoreras:
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]
public class Person { ... }
I System.Text.Jsonkan du ange beteendet för alla typer och egenskaper:
JsonSerializerOptions options = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
string json = JsonSerializer.Serialize<Person>(person, options);
Eller så kan du ange beteendet för varje egenskap separat:
public class Person
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Name { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Age { get; set; }
}
Tänk sedan på följande exempel som används Newtonsoft.Json.JsonObjectAttribute
för att ange att alla medlemsegenskaper måste finnas i JSON:
[JsonObject(ItemRequired = Required.Always)]
public class Person { ... }
Du kan uppnå samma beteende i System.Text.Json genom att lägga till C#- required
modifieraren eller JsonRequiredAttribute till varje egenskap. Mer information finns i Obligatoriska egenskaper.
public class Person
{
[JsonRequired]
public string? Name { get; set; }
public required int? Age { get; set; }
}
TraceWriter
Newtonsoft.Json
låter dig felsöka med hjälp av en TraceWriter
för att visa loggar som genereras av serialisering eller deserialisering. System.Text.Json loggning.
JsonDocument och JsonElement jämfört med JToken (som JObject, JArray)
System.Text.Json.JsonDocument ger möjlighet att parsa och skapa en skrivskyddad dokumentobjektmodell (DOM) från befintliga JSON-nyttolaster. DOM ger slumpmässig åtkomst till data i en JSON-nyttolast. JSON-elementen som utgör nyttolasten kan nås via JsonElement typen . Typen JsonElement
innehåller API:er för att konvertera JSON-text till vanliga .NET-typer. JsonDocument
exponerar en RootElement egenskap.
Från och med .NET 6 kan du parsa och skapa en föränderlig DOM från befintliga JSON-nyttolaster med hjälp JsonNode av typen och andra typer i System.Text.Json.Nodes namnområdet. Mer information finns i Använda JsonNode
.
JsonDocument är IDisposable
JsonDocument
skapar en minnesintern vy över data till en poolbuffert. Till skillnad från JObject
eller JArray
från Newtonsoft.Json
JsonDocument
implementerar IDisposable
typen därför och måste användas i ett användningsblock. Mer information finns i JsonDocument is IDisposable (JsonDocument is IDisposable).
JsonDocument är skrivskyddat
DOM System.Text.Json kan inte lägga till, ta bort eller ändra JSON-element. Det är utformat på det här sättet för prestanda och för att minska allokering för parsning av vanliga JSON-nyttolaststorlekar (det vill: < 1 MB).
JsonElement är en union struct
JsonDocument
exponerar RootElement
som en egenskap av typen JsonElement, som är en union struct-typ som omfattar alla JSON-element. Newtonsoft.Json
använder dedikerade hierarkiska typer som JObject
, JArray
, JToken
och så vidare. JsonElement
är det du kan söka efter och räkna upp och du kan använda JsonElement
för att materialisera JSON-element till .NET-typer.
Från och med .NET 6 kan du använda JsonNode typ och typer i namnområdet System.Text.Json.Nodes som motsvarar JObject
, JArray
och JToken
. Mer information finns i Använda JsonNode
.
Så här söker du efter underelement i JsonDocument och JsonElement
Sökningar efter JSON-token som använder JObject
eller JArray
från Newtonsoft.Json
tenderar att vara relativt snabba eftersom de är sökningar i någon ordlista. Som jämförelse kräver sökningar på JsonElement
en sekventiell sökning av egenskaperna och är därför relativt långsamma (till exempel när du använder TryGetProperty
). System.Text.Json är utformad för att minimera den inledande parsningstiden i stället för uppslagstiden. Mer information finns i Så här söker du efter underelement i JsonDocument och JsonElement.
Utf8JsonReader jämfört med JsonTextReader
System.Text.Json.Utf8JsonReaderär en högpresterande, låg allokering, framåtriktad läsare för UTF-8-kodad JSON-text, läs från en ReadOnlySpan-byte<> eller ReadOnlySequence-byte.<> Utf8JsonReader
är en lågnivåtyp som kan användas för att skapa anpassade parsers och deserializers.
Utf8JsonReader är en referensstruct
In JsonTextReader
Newtonsoft.Json
är en klass. Typen Utf8JsonReader
skiljer sig åt eftersom det är en referens-struct. Mer information finns i referensstruktureringsbegränsningar för Utf8JsonReader.
Läsa null-värden i null-värdetyper
Newtonsoft.Json
tillhandahåller API:er som returnerar Nullable<T>, till exempel ReadAsBoolean
, som hanterar en Null
TokenType
åt dig genom att returnera en bool?
. De inbyggda System.Text.Json
API:erna returnerar endast icke-nullbara värdetyper. Mer information finns i Läsa null-värden i null-värdetyper.
Flera mål för att läsa JSON
Om du behöver fortsätta att använda Newtonsoft.Json
för vissa målramverk kan du använda flera mål och ha två implementeringar. Detta är dock inte trivialt och skulle kräva viss #ifdefs
och källduplicering. Ett sätt att dela så mycket kod som möjligt är att skapa en ref struct
omslutning runt Utf8JsonReader och Newtonsoft.Json.JsonTextReader
. Den här omslutningen skulle förena den offentliga ytan samtidigt som beteendeskillnaderna isoleras. På så sätt kan du isolera ändringarna främst i konstruktionen av typen, tillsammans med att skicka den nya typen runt som referens. Det här är det mönster som biblioteket Microsoft.Extensions.DependencyModel följer:
Utf8JsonWriter jämfört med JsonTextWriter
System.Text.Json.Utf8JsonWriter är ett högpresterande sätt att skriva UTF-8-kodad JSON-text från vanliga .NET-typer som String
, Int32
och DateTime
. Skrivaren är en lågnivåtyp som kan användas för att skapa anpassade serialiserare.
Skriva raw-värden
Newtonsoft.Json
har en WriteRawValue
metod som skriver rå JSON där ett värde förväntas. System.Text.Json har en direkt motsvarighet: Utf8JsonWriter.WriteRawValue. Mer information finns i Skriva rå JSON.
Anpassa JSON-format
JsonTextWriter
innehåller följande inställningar som Utf8JsonWriter inte har någon motsvarighet:
- QuoteChar – Anger det tecken som ska användas för att omge strängvärden.
Utf8JsonWriter
använder alltid dubbla citattecken. - QuoteName – Anger om egenskapsnamn ska omges av citattecken eller inte.
Utf8JsonWriter
omger dem alltid med citattecken.
Från och med .NET 9 kan du anpassa indragstecknet och storleken för Utf8JsonWriter att använda alternativ som exponeras av struct:JsonWriterOptions
JsonTextWriter
innehåller följande inställningar som Utf8JsonWriter
inte har någon motsvarighet:
- Indrag – Anger hur många tecken som ska dras in.
Utf8JsonWriter
indrag med 2 tecken. - IndentChar – Anger det tecken som ska användas för indrag.
Utf8JsonWriter
använder alltid blanksteg. - QuoteChar – Anger det tecken som ska användas för att omge strängvärden.
Utf8JsonWriter
använder alltid dubbla citattecken. - QuoteName – Anger om egenskapsnamn ska omges av citattecken eller inte.
Utf8JsonWriter
omger dem alltid med citattecken.
Det finns inga lösningar som gör att du kan anpassa JSON som skapats av Utf8JsonWriter
på dessa sätt.
Skriv tidsintervall, Uri eller teckenvärden
JsonTextWriter
innehåller WriteValue
metoder för TimeSpan-, Uri- och char-värden . Utf8JsonWriter
har inte motsvarande metoder. Formatera i stället dessa värden som strängar (genom att anropa ToString()
, till exempel) och anropa WriteStringValue.
Flera mål för att skriva JSON
Om du behöver fortsätta att använda Newtonsoft.Json
för vissa målramverk kan du använda flera mål och ha två implementeringar. Detta är dock inte trivialt och skulle kräva viss #ifdefs
och källduplicering. Ett sätt att dela så mycket kod som möjligt är att skapa en omslutning runt Utf8JsonWriter och Newtonsoft.Json.JsonTextWriter
. Den här omslutningen skulle förena den offentliga ytan samtidigt som beteendeskillnaderna isoleras. På så sätt kan du isolera ändringarna främst i konstruktionen av typen. Microsoft.Extensions.DependencyModel-biblioteket följer:
TypeNameHandling.All stöds inte
Beslutet att undanta TypeNameHandling.All
-motsvarande funktioner från System.Text.Json
var avsiktligt. Att tillåta en JSON-nyttolast att ange sin egen typinformation är en vanlig källa till sårbarheter i webbprogram. I synnerhet gör konfigurationen Newtonsoft.Json
med TypeNameHandling.All
att fjärrklienten kan bädda in ett helt körbart program i själva JSON-nyttolasten, så att webbprogrammet extraherar och kör den inbäddade koden under deserialiseringen. Mer information finns i Fredag den 13: e JSON-attacker PowerPoint och fredag den 13: e JSON-attacker information.
JSON-sökvägsfrågor stöds inte
JsonDocument
DOM stöder inte frågor med hjälp av JSON-sökväg.
I en JsonNode DOM har varje JsonNode
instans en GetPath
metod som returnerar en sökväg till noden. Men det finns inget inbyggt API för att hantera frågor baserat på frågesträngar för JSON-sökväg.
Mer information finns i GitHub-problemet dotnet/runtime #31068.
Vissa gränser kan inte konfigureras
System.Text.Json anger gränser som inte kan ändras för vissa värden, till exempel den maximala tokenstorleken i tecken (166 MB) och i bas 64 (125 MB). Mer information JsonConstants
finns i källkoden och GitHub-problemet dotnet/runtime #39953.
NaN, Infinity, -Infinity
Newtonsoft parsar NaN
, Infinity
och -Infinity
JSON-strängtoken. Med System.Text.Jsonanvänder du JsonNumberHandling.AllowNamedFloatingPointLiterals. Information om hur du använder den här inställningen finns i Tillåt eller skriva tal inom citattecken.
Använda GitHub Copilot för att migrera
Du kan få kodningshjälp från GitHub Copilot för att konvertera din kod i din IDE.
Om du använder Visual Studio 2022 version 17.8 eller senare kan du prova den AI-drivna GitHub Copilot i Visual Studio för att migrera koden Newtonsoft.Json
för att använda System.Text.Json
. Skicka din fråga och koden för att konvertera som en uppmaning i chattfönstret copilot, som i följande exempel.
Kommentar
GitHub Copilot drivs av AI, så överraskningar och misstag är möjliga. Kontrollera eventuell genererad kod eller förslag. Mer information om allmän användning av GitHub Copilot, produktpåverkan, mänsklig tillsyn och sekretess finns i Vanliga frågor och svar om GitHub Copilot.
Exempelfråga för 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);
Exempel på Copilot Chat-svar
To convert the code to use System.Text.Json, you can use the JsonSerializer class. Here's the updated code:
using System;
using System.Text.Json;
public class Product
{
public string Name { get; set; }
public DateTime ExpiryDate { get; set; }
public decimal Price { get; set; }
public string[] Sizes { get; set; }
}
public class Program
{
public static void Main()
{
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 = JsonSerializer.Serialize(product);
Console.WriteLine(output);
}
}
This code uses System.Text.Json.JsonSerializer.Serialize to convert the Product object to a JSON string.
Observera att dina resultat kan skilja sig från vad som visas i dessa exempelsvar. AI-modeller är icke-deterministiska, vilket innebär att de kan returnera olika svar när de får samma fråga. Detta kan bero på ytterligare inlärning och anpassning över tid, språkvariationer, ändringar i kontexten, till exempel din chatthistorik med mera.
Du kan använda chattfunktioner, till exempel snedstreckskommandon, referenser och trådar, för att ange avsikt och få bättre svar med begränsad kontext.
Om din kodfil filename
till exempel är öppen i IDE kan du referera till filen i din uppmaning till Copilot Chat med "convert #filename
to use System.Text.Json
". Eller så kan du referera till lösningen med "konvertera @workspace
till användning System.Text.Json
" i chattfönstret eller i infogad chatt.