Jak používat generování zdroje v System.Text.Json

Generování zdrojového kódu System.Text.Json je k dispozici v .NET 6 a novějších verzích. Při použití v aplikaci musí být jazyková verze aplikace C# 9.0 nebo novější. V tomto článku se dozvíte, jak ve svých aplikacích používat serializaci založené na zdrojové generaci.

Informace o různých režimech generování zdroje najdete v tématu Režimy generování zdroje.

Použití výchozích hodnot generování zdroje

Použití generování zdroje se všemi výchozími nastaveními (oba režimy, výchozí možnosti):

  1. Vytvořte částečnou třídu, která je odvozena od JsonSerializerContext.

  2. Zadejte typ pro serializaci nebo deserializaci použitím JsonSerializableAttribute třídy kontextu.

  3. Volejte metodu JsonSerializer , která:

Ve výchozím nastavení se používají oba režimy generování zdroje, pokud ho nezadáte. Informace o tom, jak určit režim, který se má použít, naleznete v části Určení režimu generování zdroje dále v tomto článku.

Tady je typ, který se používá v následujících příkladech:

public class WeatherForecast
{
    public DateTime Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public string? Summary { get; set; }
}

Tady je kontextová třída nakonfigurovaná tak, aby generovala zdroj pro předchozí WeatherForecast třídu:

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}

Typy WeatherForecast členů není nutné explicitně zadávat pomocí [JsonSerializable] atributů. Členové deklarovaní jako object výjimka tohoto pravidla. Typ modulu runtime pro člen deklarovaný podle object potřeby. Předpokládejme například, že máte následující třídu:

public class WeatherForecast
{
    public object? Data { get; set; }
    public List<object>? DataList { get; set; }
}

A víte, že za běhu může mít boolean a int objekty:

WeatherForecast wf = new() { Data = true, DataList = new List<object> { true, 1 } };

Pak boolean je int nutné deklarovat jako [JsonSerializable]:

[JsonSerializable(typeof(WeatherForecast))]
[JsonSerializable(typeof(bool))]
[JsonSerializable(typeof(int))]
public partial class WeatherForecastContext : JsonSerializerContext
{
}

Chcete-li zadat generování zdroje pro kolekci, použijte [JsonSerializable] s typem kolekce. Například: [JsonSerializable(typeof(List<WeatherForecast>))].

JsonSerializer metody, které používají generování zdroje

V následujících příkladech statická Default vlastnost typu kontextu poskytuje instanci typu kontextu s výchozími možnostmi. Instance kontextu poskytuje WeatherForecast vlastnost, která vrací JsonTypeInfo<WeatherForecast> instanci. Pro tuto vlastnost můžete zadat jiný název pomocí TypeInfoPropertyName vlastnosti atributu [JsonSerializable] .

Příklady serializace

Pomocí JsonTypeInfo<T>:

jsonString = JsonSerializer.Serialize(
    weatherForecast!, SourceGenerationContext.Default.WeatherForecast);

Pomocí JsonSerializerContext:

jsonString = JsonSerializer.Serialize(
    weatherForecast, typeof(WeatherForecast), SourceGenerationContext.Default);

Pomocí JsonSerializerOptions:

sourceGenOptions = new JsonSerializerOptions
{
    TypeInfoResolver = SourceGenerationContext.Default
};

jsonString = JsonSerializer.Serialize(
    weatherForecast, typeof(WeatherForecast), sourceGenOptions);

Příklady deserializace

Pomocí JsonTypeInfo<T>:

weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
    jsonString, SourceGenerationContext.Default.WeatherForecast);

Pomocí JsonSerializerContext:

weatherForecast = JsonSerializer.Deserialize(
    jsonString, typeof(WeatherForecast), SourceGenerationContext.Default)
    as WeatherForecast;

Pomocí JsonSerializerOptions:

var sourceGenOptions = new JsonSerializerOptions
{
    TypeInfoResolver = SourceGenerationContext.Default
};
weatherForecast = JsonSerializer.Deserialize(
    jsonString, typeof(WeatherForecast), sourceGenOptions)
    as WeatherForecast;

Příklad kompletního programu

Tady jsou předchozí příklady v úplném programu:

using System.Text.Json;
using System.Text.Json.Serialization;

namespace BothModesNoOptions
{
    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureCelsius { get; set; }
        public string? Summary { get; set; }
    }

    [JsonSourceGenerationOptions(WriteIndented = true)]
    [JsonSerializable(typeof(WeatherForecast))]
    internal partial class SourceGenerationContext : JsonSerializerContext
    {
    }

    public class Program
    {
        public static void Main()
        {
            string jsonString = """
                {
                    "Date": "2019-08-01T00:00:00",
                    "TemperatureCelsius": 25,
                    "Summary": "Hot"
                }
                """;
            WeatherForecast? weatherForecast;

            weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
                jsonString, SourceGenerationContext.Default.WeatherForecast);
            Console.WriteLine($"Date={weatherForecast?.Date}");
            // output:
            //Date=8/1/2019 12:00:00 AM

            weatherForecast = JsonSerializer.Deserialize(
                jsonString, typeof(WeatherForecast), SourceGenerationContext.Default)
                as WeatherForecast;
            Console.WriteLine($"Date={weatherForecast?.Date}");
            // output:
            //Date=8/1/2019 12:00:00 AM

            var sourceGenOptions = new JsonSerializerOptions
            {
                TypeInfoResolver = SourceGenerationContext.Default
            };
            weatherForecast = JsonSerializer.Deserialize(
                jsonString, typeof(WeatherForecast), sourceGenOptions)
                as WeatherForecast;
            Console.WriteLine($"Date={weatherForecast?.Date}");
            // output:
            //Date=8/1/2019 12:00:00 AM

            jsonString = JsonSerializer.Serialize(
                weatherForecast!, SourceGenerationContext.Default.WeatherForecast);
            Console.WriteLine(jsonString);
            // output:
            //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}

            jsonString = JsonSerializer.Serialize(
                weatherForecast, typeof(WeatherForecast), SourceGenerationContext.Default);
            Console.WriteLine(jsonString);
            // output:
            //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}

            sourceGenOptions = new JsonSerializerOptions
            {
                TypeInfoResolver = SourceGenerationContext.Default
            };

            jsonString = JsonSerializer.Serialize(
                weatherForecast, typeof(WeatherForecast), sourceGenOptions);
            Console.WriteLine(jsonString);
            // output:
            //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}
        }
    }
}

Určení režimu generování zdroje

Můžete zadat režim založený na metadatech nebo režim optimalizace serializace pro celý kontext, který může obsahovat více typů. Nebo můžete určit režim pro jednotlivé typy. Pokud provedete obojí, specifikace režimu pro typ vyhrává.

Příklad režimu optimalizace serializace (rychlá cesta)

  • Pro celý kontext:

    [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization)]
    [JsonSerializable(typeof(WeatherForecast))]
    internal partial class SerializeOnlyContext : JsonSerializerContext
    {
    }
    
  • Pro jednotlivé typy:

    [JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Serialization)]
    internal partial class SerializeOnlyWeatherForecastOnlyContext : JsonSerializerContext
    {
    }
    
  • Příklad kompletního programu

    using System.Text.Json;
    using System.Text.Json.Serialization;
    
    namespace SerializeOnlyNoOptions
    {
        public class WeatherForecast
        {
            public DateTime Date { get; set; }
            public int TemperatureCelsius { get; set; }
            public string? Summary { get; set; }
        }
    
        [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization)]
        [JsonSerializable(typeof(WeatherForecast))]
        internal partial class SerializeOnlyContext : JsonSerializerContext
        {
        }
        
        [JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Serialization)]
        internal partial class SerializeOnlyWeatherForecastOnlyContext : JsonSerializerContext
        {
        }
    
         public class Program
        {
            public static void Main()
            {
                string jsonString;
                WeatherForecast weatherForecast = new()
                    { Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" };
    
                // Use context that selects Serialization mode only for WeatherForecast.
                jsonString = JsonSerializer.Serialize(weatherForecast,
                    SerializeOnlyWeatherForecastOnlyContext.Default.WeatherForecast);
                Console.WriteLine(jsonString);
                // output:
                //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}
    
                // Use a context that selects Serialization mode.
                jsonString = JsonSerializer.Serialize(weatherForecast,
                    SerializeOnlyContext.Default.WeatherForecast);
                Console.WriteLine(jsonString);
                // output:
                //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}
            }
        }
    }
    

Příklad režimu založeného na metadatech

  • Pro celý kontext:

    [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
    [JsonSerializable(typeof(WeatherForecast))]
    internal partial class MetadataOnlyContext : JsonSerializerContext
    {
    }
    
    jsonString = JsonSerializer.Serialize(
        weatherForecast!, MetadataOnlyContext.Default.WeatherForecast);
    
    weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
        jsonString, MetadataOnlyContext.Default.WeatherForecast);
    
  • Pro jednotlivé typy:

    [JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Metadata)]
    internal partial class MetadataOnlyWeatherForecastOnlyContext : JsonSerializerContext
    {
    }
    
    jsonString = JsonSerializer.Serialize(
        weatherForecast!,
        MetadataOnlyWeatherForecastOnlyContext.Default.WeatherForecast);
    
    weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
        jsonString, MetadataOnlyWeatherForecastOnlyContext.Default.WeatherForecast);
    
  • Příklad kompletního programu

    using System.Text.Json;
    using System.Text.Json.Serialization;
    
    namespace MetadataOnlyNoOptions
    {
        public class WeatherForecast
        {
            public DateTime Date { get; set; }
            public int TemperatureCelsius { get; set; }
            public string? Summary { get; set; }
        }
    
        [JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Metadata)]
        internal partial class MetadataOnlyWeatherForecastOnlyContext : JsonSerializerContext
        {
        }
    
        [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
        [JsonSerializable(typeof(WeatherForecast))]
        internal partial class MetadataOnlyContext : JsonSerializerContext
        {
        }
    
        public class Program
        {
            public static void Main()
            {
                string jsonString = """
                    {
                      "Date": "2019-08-01T00:00:00",
                      "TemperatureCelsius": 25,
                      "Summary": "Hot"
                    }
                    """;
                WeatherForecast? weatherForecast;
    
                // Deserialize with context that selects metadata mode only for WeatherForecast only.
                weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
                    jsonString, MetadataOnlyWeatherForecastOnlyContext.Default.WeatherForecast);
                Console.WriteLine($"Date={weatherForecast?.Date}");
                // output:
                //Date=8/1/2019 12:00:00 AM
    
                // Serialize with context that selects metadata mode only for WeatherForecast only.
                jsonString = JsonSerializer.Serialize(
                    weatherForecast!,
                    MetadataOnlyWeatherForecastOnlyContext.Default.WeatherForecast);
                Console.WriteLine(jsonString);
                // output:
                //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}
    
                // Deserialize with context that selects metadata mode only.
                weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
                    jsonString, MetadataOnlyContext.Default.WeatherForecast);
                Console.WriteLine($"Date={weatherForecast?.Date}");
                // output:
                //Date=8/1/2019 12:00:00 AM
    
                // Serialize with context that selects metadata mode only.
                jsonString = JsonSerializer.Serialize(
                    weatherForecast!, MetadataOnlyContext.Default.WeatherForecast);
                Console.WriteLine(jsonString);
                // output:
                //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":0,"Summary":"Hot"}
            }
        }
    }
    

Podpora generování zdrojového kódu v ASP.NET Core

V aplikacích Blazor použijte přetížení HttpClientJsonExtensions.GetFromJsonAsync a HttpClientJsonExtensions.PostAsJsonAsync rozšiřující metody, které využívají kontext generování zdroje nebo TypeInfo<TValue>.

Počínaje rozhraním .NET 8 můžete také použít přetížení rozšiřujících HttpClientJsonExtensions.GetFromJsonAsAsyncEnumerable metod, které přijímají kontext generování zdroje nebo TypeInfo<TValue>.

V aplikacích Razor Pages, MVC, SignalR a Web API použijte JsonSerializerOptions.TypeInfoResolver vlastnost k určení kontextu.

[JsonSerializable(typeof(WeatherForecast[]))]
internal partial class MyJsonContext : JsonSerializerContext { }
var serializerOptions = new JsonSerializerOptions
{
    TypeInfoResolver = MyJsonContext.Default
};

services.AddControllers().AddJsonOptions(
    static options =>
        options.JsonSerializerOptions.TypeInfoResolverChain.Add(MyJsonContext.Default));

V aplikacích Razor Pages, MVC, SignalR a Web API použijte JsonSerializerOptions.TypeInfoResolver vlastnost k určení kontextu.

[JsonSerializable(typeof(WeatherForecast[]))]
internal partial class MyJsonContext : JsonSerializerContext { }
var serializerOptions = new JsonSerializerOptions
{
    TypeInfoResolver = MyJsonContext.Default
};

services.AddControllers().AddJsonOptions(
    static options =>
        options.JsonSerializerOptions = serializerOptions);

V aplikacích Razor Pages, MVC, SignalR a Web API použijte AddContext metodu JsonSerializerOptions, jak je znázorněno v následujícím příkladu:

[JsonSerializable(typeof(WeatherForecast[]))]
internal partial class MyJsonContext : JsonSerializerContext { }
services.AddControllers().AddJsonOptions(options =>
    options.JsonSerializerOptions.AddContext<MyJsonContext>());

Poznámka:

JsonSourceGenerationMode.Serializationserializace s rychlou cestou není podporována pro asynchronní serializaci.

V .NET 7 a starších verzích se toto omezení vztahuje také na synchronní přetížení JsonSerializer.Serialize , které přijímají Stream. Počínaje rozhraním .NET 8, i když serializace streamování vyžaduje modely založené na metadatech, vrátí se k rychlé cestě, pokud jsou datové části známé, že jsou dostatečně malé, aby se vešly do předem určené velikosti vyrovnávací paměti. Další informace najdete na webu https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#json.

Zakázání výchozích hodnot reflexe

Vzhledem k tomu, že System.Text.Json se ve výchozím nastavení používá reflexe, může volání základní metody serializace narušit nativní aplikace AOT, které nepodporují všechna požadovaná rozhraní API reflexe. Tyto přestávky můžou být náročné diagnostikovat, protože můžou být nepředvídatelné a aplikace se často ladí pomocí modulu runtime CoreCLR, kde funguje reflexe. Pokud místo toho explicitně zakážete serializaci založenou na reflexi, je snazší diagnostikovat konce. Kód, který používá serializaci založenou na reflexi, způsobí InvalidOperationException vyvolání popisné zprávy za běhu.

Pokud chcete ve své aplikaci zakázat výchozí reflexi, nastavte JsonSerializerIsReflectionEnabledByDefault vlastnost MSBuild do false souboru projektu:

<PropertyGroup>
  <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
  • Chování této vlastnosti je konzistentní bez ohledu na modul runtime, buď CoreCLR, nebo nativní AOT.
  • Pokud tuto vlastnost nezadáte a funkce PublishTrimmed je povolená , serializace založená na reflexi se automaticky zakáže.

Pomocí této vlastnosti můžete programově zkontrolovat, jestli je reflexe zakázaná JsonSerializer.IsReflectionEnabledByDefault . Následující fragment kódu ukazuje, jak můžete serializátor nakonfigurovat v závislosti na tom, jestli je reflexe povolená:

static JsonSerializerOptions CreateDefaultOptions()
{
    return new()
    {
        TypeInfoResolver = JsonSerializer.IsReflectionEnabledByDefault
            ? new DefaultJsonTypeInfoResolver()
            : MyContext.Default
    };
}

Vzhledem k tomu, že vlastnost je považována za konstantu link-time, předchozí metoda neuloží překladač založený na reflexi v aplikacích, které běží v nativní AOT.

Zadání možností

V .NET 8 a novějších verzích lze většinu možností, které můžete použít JsonSerializerOptions , nastavit také pomocí atributu JsonSourceGenerationOptionsAttribute . Výhodou nastavení možností prostřednictvím atributu je to, že konfigurace je určena v době kompilace, což zajišťuje, že vygenerovaná MyContext.Default vlastnost je předem nakonfigurovaná se všemi příslušnými sadami možností.

Následující kód ukazuje, jak nastavit možnosti pomocí atributu JsonSourceGenerationOptionsAttribute .

[JsonSourceGenerationOptions(
    WriteIndented = true,
    PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
    GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SerializationModeOptionsContext : JsonSerializerContext
{
}

Při použití JsonSourceGenerationOptionsAttribute k určení možností serializace, zavolejte jednu z následujících metod serializace:

  • Metoda JsonSerializer.Serialize , která přebírá TypeInfo<TValue>. Předejte vlastnost Default.<TypeName> vaší třídy kontextu:

    jsonString = JsonSerializer.Serialize(
        weatherForecast, SerializationModeOptionsContext.Default.WeatherForecast);
    
  • Metoda JsonSerializer.Serialize , která přebírá kontext. Předejte ji Default statickou vlastnost vaší třídy kontextu.

    jsonString = JsonSerializer.Serialize(
        weatherForecast, typeof(WeatherForecast), SerializationModeOptionsContext.Default);
    

Pokud voláte metodu, která vám umožní předat vlastní instanci Utf8JsonWriter, nastavení zapisovače Indented se respektuje místo JsonSourceGenerationOptionsAttribute.WriteIndented možnosti.

Pokud vytvoříte a použijete kontextovou instanci voláním konstruktoru JsonSerializerOptions , který přebírá instanci, bude zadaná instance použita místo možností určených JsonSourceGenerationOptionsAttribute.

Tady jsou předchozí příklady v úplném programu:

using System.Text.Json;
using System.Text.Json.Serialization;

namespace SerializeOnlyWithOptions
{
    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureCelsius { get; set; }
        public string? Summary { get; set; }
    }

    [JsonSourceGenerationOptions(
        WriteIndented = true,
        PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
        GenerationMode = JsonSourceGenerationMode.Serialization)]
    [JsonSerializable(typeof(WeatherForecast))]
    internal partial class SerializationModeOptionsContext : JsonSerializerContext
    {
    }
    public class Program
    {
        public static void Main()
        {
            string jsonString;
            WeatherForecast weatherForecast = new()
                { Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" };

            // Serialize using TypeInfo<TValue> provided by the context
            // and options specified by [JsonSourceGenerationOptions].
            jsonString = JsonSerializer.Serialize(
                weatherForecast, SerializationModeOptionsContext.Default.WeatherForecast);
            Console.WriteLine(jsonString);
            // output:
            //{
            //  "date": "2019-08-01T00:00:00",
            //  "temperatureCelsius": 0,
            //  "summary": "Hot"
            //}

            // Serialize using Default context
            // and options specified by [JsonSourceGenerationOptions].
            jsonString = JsonSerializer.Serialize(
                weatherForecast, typeof(WeatherForecast), SerializationModeOptionsContext.Default);
            Console.WriteLine(jsonString);
            // output:
            //{
            //  "date": "2019-08-01T00:00:00",
            //  "temperatureCelsius": 0,
            //  "summary": "Hot"
            //}
        }
    }
}

Určení možností pomocí JsonSerializerOptions

Některé možnosti JsonSerializerOptions nejde nastavit pomocí JsonSourceGenerationOptionsAttribute. Určení možností pomocí:JsonSerializerOptions

  • Vytvořte instanci JsonSerializerOptions.
  • Vytvořte instanci vaší třídy, která je odvozena od JsonSerializerContexta předat JsonSerializerOptions instanci konstruktoru.
  • Volání serializace nebo deserializační metody JsonSerializer , které přebírají kontextovou instanci nebo TypeInfo<TValue>.

Tady je příklad třídy kontextu následované serializací a deserializačním ukázkovým kódem:

[JsonSerializable(typeof(WeatherForecast))]
internal partial class OptionsExampleContext : JsonSerializerContext
{
}
jsonString = JsonSerializer.Serialize(
    weatherForecast,
    typeof(WeatherForecast),
    new OptionsExampleContext(
        new JsonSerializerOptions(JsonSerializerDefaults.Web)));
weatherForecast = JsonSerializer.Deserialize(
    jsonString, 
    typeof(WeatherForecast), 
    new OptionsExampleContext(
        new JsonSerializerOptions(JsonSerializerDefaults.Web)))
        as WeatherForecast;

Tady jsou předchozí příklady v úplném programu:

using System.Text.Json;
using System.Text.Json.Serialization;

namespace JsonSerializerOptionsExample
{
    public class WeatherForecast
    {
        public DateTime Date { get; set; }
        public int TemperatureCelsius { get; set; }
        public string? Summary { get; set; }
    }

    [JsonSerializable(typeof(WeatherForecast))]
    internal partial class OptionsExampleContext : JsonSerializerContext
    {
    }

    public class Program
    {
        public static void Main()
        {
            string jsonString = """
                {
                  "date": "2019-08-01T00:00:00",
                  "temperatureCelsius": 25,
                  "summary": "Hot"
                }
                """;
            WeatherForecast? weatherForecast;

            weatherForecast = JsonSerializer.Deserialize(
                jsonString, 
                typeof(WeatherForecast), 
                new OptionsExampleContext(
                    new JsonSerializerOptions(JsonSerializerDefaults.Web)))
                    as WeatherForecast;
            Console.WriteLine($"Date={weatherForecast?.Date}");
            // output:
            //Date=8/1/2019 12:00:00 AM

            jsonString = JsonSerializer.Serialize(
                weatherForecast,
                typeof(WeatherForecast),
                new OptionsExampleContext(
                    new JsonSerializerOptions(JsonSerializerDefaults.Web)));
            Console.WriteLine(jsonString);
            // output:
            //{ "date":"2019-08-01T00:00:00","temperatureCelsius":25,"summary":"Hot"}
        }
    }
}

Kombinování generátorů zdrojů

Kontrakty z několika kontextů vygenerovaných zdrojem můžete kombinovat v jedné JsonSerializerOptions instanci. JsonSerializerOptions.TypeInfoResolver Pomocí vlastnosti zřetězte více kontextů, které byly kombinovány pomocí JsonTypeInfoResolver.Combine(IJsonTypeInfoResolver[]) metody.

var options = new JsonSerializerOptions
{
    TypeInfoResolver = JsonTypeInfoResolver.Combine(ContextA.Default, ContextB.Default, ContextC.Default);
};

Počínaje rozhraním .NET 8, pokud později chcete předem připojit nebo připojit jiný kontext, můžete to provést pomocí JsonSerializerOptions.TypeInfoResolverChain vlastnosti. Řazení řetězce je významné: JsonSerializerOptions dotazuje se na každý z překladačů v zadaném pořadí a vrátí první výsledek, který není null.

options.TypeInfoResolverChain.Add(ContextD.Default); // Append to the end of the list.
options.TypeInfoResolverChain.Insert(0, ContextE.Default); // Insert at the beginning of the list.

Všechny změny provedené ve TypeInfoResolverChain vlastnosti se projeví TypeInfoResolver naopak.

Serializace výčtových polí jako řetězců

Ve výchozím nastavení jsou výčty serializovány jako čísla. Pokud chcete serializovat pole určitého výčtu jako řetězce při použití generování zdroje, anotujte je pomocí převaděče JsonStringEnumConverter<TEnum> . Nebo nastavit deka zásady pro všechny výčty, použijte JsonSourceGenerationOptionsAttribute atribut.

JsonStringEnumConverter<T> Converter

Chcete-li serializovat názvy výčtů jako řetězce pomocí generování zdroje, použijte JsonStringEnumConverter<TEnum> převaděč. (Nativní modul runtime AOT nepodporuje obecný JsonStringEnumConverter typ.)

Anotujte typ výčtu pomocí převaděče JsonStringEnumConverter<TEnum> pomocí atributu JsonConverterAttribute :

public class WeatherForecastWithPrecipEnum
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public Precipitation? Precipitation { get; set; }
}

[JsonConverter(typeof(JsonStringEnumConverter<Precipitation>))]
public enum Precipitation
{
    Drizzle, Rain, Sleet, Hail, Snow
}

Vytvořte JsonSerializerContext třídu a označte ji pomocí atributu JsonSerializableAttribute :

[JsonSerializable(typeof(WeatherForecastWithPrecipEnum))]
public partial class Context1 : JsonSerializerContext { }

Následující kód serializuje názvy výčtů místo číselných hodnot:

var weatherForecast = new WeatherForecastWithPrecipEnum
{
    Date = DateTime.Parse("2019-08-01"),
    TemperatureCelsius = 25,
    Precipitation = Precipitation.Sleet
};

var options = new JsonSerializerOptions
{
    WriteIndented = true,
    TypeInfoResolver = Context1.Default,
};
string? jsonString = JsonSerializer.Serialize(weatherForecast, options);

Výsledný json vypadá jako v následujícím příkladu:

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Precipitation": "Sleet"
}

Zásady deky

Místo použití JsonStringEnumConverter<TEnum> typu můžete použít deka zásady serializace výčtů jako řetězce pomocí JsonSourceGenerationOptionsAttribute. Vytvořte JsonSerializerContext třídu a označte ji poznámkami JsonSerializableAttributea JsonSourceGenerationOptionsAttribute atributy:

[JsonSourceGenerationOptions(UseStringEnumConverter = true)]
[JsonSerializable(typeof(WeatherForecast2WithPrecipEnum))]
public partial class Context2 : JsonSerializerContext { }

Všimněte si, že výčt nemá následující JsonConverterAttribute:

public class WeatherForecast2WithPrecipEnum
{
    public DateTimeOffset Date { get; set; }
    public int TemperatureCelsius { get; set; }
    public Precipitation2? Precipitation { get; set; }
}

public enum Precipitation2
{
    Drizzle, Rain, Sleet, Hail, Snow
}

Viz také