Dela via


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är Newtonsoft.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

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:

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.Jsonaccepterar 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 och DefaultValueHandlingJsonSerializerSettings kan du ange att alla null-värde- eller standardvärdeegenskaper ska ignoreras.
  • Med NullValueHandling inställningarna och DefaultValueHandling 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:

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.

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.JsonTKey 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:

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 lagrade string, long, double, booleaneller DateTime som ett rutat objekt. Primitiva värden är enkla JSON-värden, till exempel ett JSON-tal, en sträng, true, falseeller null.
  • Returnerar ett JObject eller JArray 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.Jsonanger 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.

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 alla DateTime värden som UTC-datum.
  • Inställningen DateFormatString och DateTime 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.

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.

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"

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:

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.JsonJsonDocument 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, JTokenoch 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, JArrayoch 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, Int32och 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, Infinityoch -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.

Animerad skärmbild som visar hur du använder GitHub Copilot Chat i Visual Studio för att migrera från newtonsoft

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.

Ytterligare resurser