Bagikan melalui


Cara menggunakan pembuatan sumberSystem.Text.Json

Pembuatan sumber System.Text.Json tersedia dalam .NET 6 dan versi yang lebih baru. Saat digunakan dalam aplikasi, versi bahasa aplikasi harus C# 9.0 atau yang lebih baru. Artikel ini memperlihatkan kepada Anda cara menggunakan serialisasi yang didukung generasi sumber di aplikasi Anda.

Untuk informasi tentang berbagai mode pembuatan sumber, lihat Mode pembuatan sumber.

Menggunakan default pembuatan sumber

Untuk menggunakan pembuatan sumber dengan semua default (kedua mode, opsi default):

  1. Membuat kelas yang berasal dari JsonSerializerContext.

  2. Tentukan jenis yang akan diserialisasikan atau deserialisasikan dengan menerapkan JsonSerializableAttribute ke kelas konteks.

  3. JsonSerializer Panggil metode yang:

Secara default, kedua mode pembuatan sumber digunakan jika Anda tidak menentukannya. Untuk informasi tentang cara menentukan mode yang akan digunakan, lihat Menentukan mode pembuatan sumber nanti di artikel ini.

Berikut adalah jenis yang digunakan dalam contoh berikut:

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

Berikut adalah kelas konteks yang dikonfigurasi untuk melakukan pembuatan sumber untuk WeatherForecast kelas sebelumnya:

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

Jenis WeatherForecast anggota tidak perlu ditentukan secara eksplisit dengan [JsonSerializable] atribut. Anggota yang dinyatakan sebagai object pengecualian untuk aturan ini. Jenis runtime bahasa umum untuk anggota yang dinyatakan perlu object ditentukan. Misalnya, Anda memiliki kode berikut:

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

Dan Anda tahu bahwa pada runtime bahasa umum dapat memiliki boolean objek dan int :

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

Kemudian boolean dan int harus dinyatakan sebagai [JsonSerializable]:

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

Untuk menentukan pembuatan sumber untuk koleksi, gunakan [JsonSerializable] dengan jenis koleksi. Sebagai contoh: [JsonSerializable(typeof(List<WeatherForecast>))].

JsonSerializer metode yang menggunakan pembuatan sumber

Dalam contoh berikut, properti statis Default dari jenis konteks menyediakan instans jenis konteks dengan opsi default. Instans konteks menyediakan WeatherForecast properti yang mengembalikan instans JsonTypeInfo<WeatherForecast>. Anda dapat menentukan nama yang berbeda untuk properti ini dengan menggunakan TypeInfoPropertyName properti dari [JsonSerializable] atribut .

Contoh serialisasi

Menggunakan JsonTypeInfo<T>:

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

Menggunakan JsonSerializerContext:

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

Menggunakan JsonSerializerOptions:

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

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

Contoh deserialisasi

Menggunakan JsonTypeInfo<T>:

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

Menggunakan JsonSerializerContext:

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

Menggunakan JsonSerializerOptions:

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

Contoh program lengkap

Berikut adalah contoh sebelumnya dalam program lengkap:

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

Tentukan mode pembuatan sumber

Anda dapat menentukan mode berbasis metadata atau mode pengoptimalan serialisasi untuk seluruh konteks, yang mungkin mencakup beberapa jenis. Atau Anda dapat menentukan mode untuk jenis individual. Jika Anda melakukan keduanya, spesifikasi mode untuk jenis menang.

Contoh mode pengoptimalan serialisasi (jalur cepat)

  • Untuk seluruh konteks:

    [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization)]
    [JsonSerializable(typeof(WeatherForecast))]
    internal partial class SerializeOnlyContext : JsonSerializerContext
    {
    }
    
  • Untuk jenis individu:

    [JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Serialization)]
    internal partial class SerializeOnlyWeatherForecastOnlyContext : JsonSerializerContext
    {
    }
    
  • Contoh program lengkap

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

Contoh mode berbasis metadata

  • Untuk seluruh konteks:

    [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);
    
  • Untuk jenis individu:

    [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);
    
  • Contoh program lengkap

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

Dukungan pembuatan sumber di ASP.NET Core

Di aplikasi Blazor, gunakan kelebihan beban HttpClientJsonExtensions.GetFromJsonAsync metode ekstensi dan HttpClientJsonExtensions.PostAsJsonAsync yang mengambil konteks pembuatan sumber atau TypeInfo<TValue>.

Dimulai dengan .NET 8, Anda juga dapat menggunakan kelebihan beban HttpClientJsonExtensions.GetFromJsonAsAsyncEnumerable metode ekstensi yang menerima konteks pembuatan sumber atau TypeInfo<TValue>.

Di aplikasi Razor Pages, MVC, SignalR, dan Web API, gunakan JsonSerializerOptions.TypeInfoResolver properti untuk menentukan konteksnya.

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

Di aplikasi Razor Pages, MVC, SignalR, dan Web API, gunakan JsonSerializerOptions.TypeInfoResolver properti untuk menentukan konteksnya.

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

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

Di aplikasi Razor Pages, MVC, SignalR, dan Web API, gunakan AddContext metode JsonSerializerOptions, seperti yang ditunjukkan dalam contoh berikut:

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

Catatan

JsonSourceGenerationMode.Serialization, atau serialisasi jalur cepat, tidak didukung untuk serialisasi asinkron.

Dalam .NET 7 dan versi yang lebih lama, batasan ini juga berlaku untuk kelebihan beban sinkron yang JsonSerializer.Serialize menerima Stream. Dimulai dengan .NET 8, meskipun serialisasi streaming membutuhkan model berbasis metadata, itu akan kembali ke jalur cepat jika payload diketahui cukup kecil agar sesuai dalam ukuran buffer yang telah ditentukan. Untuk informasi selengkapnya, lihat https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#json .

Nonaktifkan default pantulan

Karena System.Text.Json menggunakan refleksi secara default, memanggil metode serialisasi dasar dapat merusak aplikasi AOT Asli, yang tidak mendukung semua API refleksi yang diperlukan. Jeda ini dapat menantang untuk didiagnosis karena dapat tidak dapat diprediksi, dan aplikasi sering di-debug menggunakan runtime CoreCLR, di mana refleksi berfungsi. Sebaliknya, jika Anda secara eksplisit menonaktifkan serialisasi berbasis refleksi, jeda lebih mudah didiagnosis. Kode yang menggunakan serialisasi berbasis refleksi akan menyebabkan InvalidOperationException dengan pesan deskriptif dilemparkan pada waktu proses.

Untuk menonaktifkan refleksi default di aplikasi Anda, atur JsonSerializerIsReflectionEnabledByDefault properti MSBuild ke false dalam file proyek Anda:

<PropertyGroup>
  <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
  • Perilaku properti ini konsisten terlepas dari runtime, baik CoreCLR atau Native AOT.
  • Jika Anda tidak menentukan properti ini dan PublishTrimmed diaktifkan, serialisasi berbasis refleksi akan dinonaktifkan secara otomatis.

Anda dapat memeriksa secara terprogram apakah refleksi dinonaktifkan dengan menggunakan JsonSerializer.IsReflectionEnabledByDefault properti . Cuplikan kode berikut menunjukkan bagaimana Anda dapat mengonfigurasi serializer bergantung pada apakah pantulan diaktifkan:

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

Karena properti diperlakukan sebagai konstanta waktu tautan, metode sebelumnya tidak mengakar resolver berbasis refleksi dalam aplikasi yang berjalan di Native AOT.

Menentukan opsi

Di .NET 8 dan versi yang lebih baru, sebagian besar opsi yang dapat Anda atur menggunakan JsonSerializerOptions juga dapat diatur menggunakan JsonSourceGenerationOptionsAttribute atribut . Keuntungan untuk mengatur opsi melalui atribut adalah bahwa konfigurasi ditentukan pada waktu kompilasi, yang memastikan bahwa properti yang dihasilkan MyContext.Default telah dikonfigurasi sebelumnya dengan semua opsi yang relevan yang ditetapkan.

Kode berikut menunjukkan cara mengatur opsi menggunakan JsonSourceGenerationOptionsAttribute atribut .

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

Saat menggunakan JsonSourceGenerationOptionsAttribute untuk menentukan opsi serialisasi, panggil salah satu metode serialisasi berikut:

  • Metode JsonSerializer.Serialize yang mengambil TypeInfo<TValue>. Teruskan Default.<TypeName> properti kelas konteks Anda:

    jsonString = JsonSerializer.Serialize(
        weatherForecast, SerializationModeOptionsContext.Default.WeatherForecast);
    
  • Metode JsonSerializer.Serialize yang mengambil. Berikan properti Default statis kelas konteks Anda.

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

Jika Anda memanggil metode yang memungkinkan Anda meneruskan instans Utf8JsonWriterAnda sendiri, pengaturan penulis Indented dihormati daripada JsonSourceGenerationOptionsAttribute.WriteIndented opsi.

Jika Anda membuat dan menggunakan instans konteks dengan memanggil konstruktor yang mengambil JsonSerializerOptions instans, instans yang disediakan akan digunakan bukan opsi yang ditentukan oleh JsonSourceGenerationOptionsAttribute.

Berikut adalah contoh sebelumnya dalam program lengkap:

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"
            //}
        }
    }
}

Tentukan opsi dengan menggunakan JsonSerializerOptions

Beberapa opsi JsonSerializerOptions tidak dapat diatur menggunakan JsonSourceGenerationOptionsAttribute. Tentukan opsi dengan menggunakan JsonSerializerOptions:

  • Buat instans JsonSerializerOptions.
  • Buat instans kelas Anda yang berasal dari JsonSerializerContext, dan teruskan JsonSerializerOptions instans ke konstruktor.
  • Panggil metode serialisasi atau deserialisasi yang JsonSerializer mengambil instans konteks atau TypeInfo<TValue>.

Berikut adalah contoh kelas konteks diikuti dengan kode contoh serialisasi dan deserialisasi:

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

Berikut adalah contoh sebelumnya dalam program lengkap:

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

Menggabungkan generator sumber

Anda dapat menggabungkan kontrak dari beberapa konteks yang dihasilkan sumber di dalam satu JsonSerializerOptions instans. Gunakan properti untuk menautkan JsonSerializerOptions.TypeInfoResolver beberapa konteks yang telah digabungkan dengan menggunakan JsonTypeInfoResolver.Combine(IJsonTypeInfoResolver[]) metode .

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

Mulai dari .NET 8, jika nanti Anda ingin menambahkan konteks lain sebelumnya atau menambahkan, Anda dapat melakukannya menggunakan JsonSerializerOptions.TypeInfoResolverChain properti . Pengurutan rantai signifikan: JsonSerializerOptions mengkueri setiap pemecah masalah dalam urutan yang ditentukan dan mengembalikan hasil pertama yang bukan 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.

Setiap perubahan yang dilakukan pada TypeInfoResolverChain properti tercermin oleh TypeInfoResolver dan sebaliknya.

Menserialisasikan bidang enum sebagai string

Secara default, enum didukung sebagai angka. Untuk membuat serialisasi bidang enum tertentu sebagai string saat menggunakan pembuatan sumber, buat anotasi dengan JsonStringEnumConverter<TEnum> pengonversi. Atau untuk mengatur kebijakan selimut untuk semua enumerasi, gunakan JsonSourceGenerationOptionsAttribute atribut .

JsonStringEnumConverter<T> Converter

Untuk menserialisasikan nama enum sebagai string menggunakan pembuatan sumber, gunakan JsonStringEnumConverter<TEnum> pengonversi. (Jenis non-generik JsonStringEnumConverter tidak didukung oleh runtime AOT Asli.)

Anotasi jenis enumerasi dengan JsonStringEnumConverter<TEnum> pengonversi menggunakan JsonConverterAttribute atribut :

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
}

Buat JsonSerializerContext kelas dan anotasi dengan JsonSerializableAttribute atribut :

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

Kode berikut menserialisasikan nama enum alih-alih nilai numerik:

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

JSON yang dihasilkan terlihat seperti contoh berikut:

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

Kebijakan selimut

Alih-alih menggunakan jenis , JsonStringEnumConverter<TEnum> Anda dapat menerapkan kebijakan selimut untuk membuat serial enum sebagai string dengan menggunakan JsonSourceGenerationOptionsAttribute. Buat kelas dan anotasi JsonSerializerContext dengan JsonSerializableAttributeatribut dan JsonSourceGenerationOptionsAttribute :

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

Perhatikan bahwa enum tidak memiliki 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
}

Lihat juga