Share via


如何在 System.Text.Json 中使用來源產生功能

System.Text.Json 中的來源產生功能可在 .NET 6 和更新版本中使用。 在應用程式中使用時,應用程式的語言版本必須是 C# 9.0 或更新版本。 本文說明如何在應用程式中使用來源產生支援的序列化。

如需不同來源產生模式的相關資訊,請參閱來源產生模式

使用來源產生功能的預設值

若要搭配使用來源產生功能及其所有預設值 (兩種模式,預設選項):

  1. 建立衍生自 JsonSerializerContext 的部分類別。

  2. 為內容類別套用 JsonSerializableAttribute,以指定要序列化或還原序列化的,類型。

  3. 呼叫下列其中一種 JsonSerializer 方法:

根據預設,若未指定來源產生模式,會使用這兩種來源產生模式。 如需如何指定所要使用之模式的詳細資訊,請參閱後文中的指定來源產生模式

以下是下列範例中使用的類型:

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

以下是設定要針對上述 WeatherForecast 類別進行來源產生的內容類別:

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

WeatherForecast 成員的類型不需要以 [JsonSerializable] 屬性明確指定。 宣告為 object 的成員是此規則的例外狀況。 必須針對宣告為 object 的成員指定執行階段類型。 舉例來說,假設您有下列類別:

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

而且您知道在執行階段可能有 booleanint 物件:

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

然後 booleanint 必須宣告為 [JsonSerializable]

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

若要指定集合的來源產生,請使用 [JsonSerializable] 搭配集合類型。 例如: [JsonSerializable(typeof(List<WeatherForecast>))]

使用來源產生的 JsonSerializer 方法

在下列範例中,內容類型的靜態 Default 屬性會提供採用預設選項的內容類型執行個體。 內容執行個體會提供的 WeatherForecast 屬性,會傳回 JsonTypeInfo<WeatherForecast> 執行個體。 您可以使用 [JsonSerializable] 屬性的 TypeInfoPropertyName 屬性,為此屬性指定其他名稱。

序列化範例

使用 JsonTypeInfo<T>

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

使用 JsonSerializerContext

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

使用 JsonSerializerOptions

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

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

還原序列化範例

使用 JsonTypeInfo<T>

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

使用 JsonSerializerContext

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

使用 JsonSerializerOptions

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

完整程式範例

以下是完整程式中的上述範例:

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

指定來源產生模式

您可以指定整個內容的中繼資料型模式或序列化最佳化模式,這可能包含多個類型。 您也可以為個別的類型指定此模式。 若兩種指定並行,會優先使用為類型指定的模式。

序列化最佳化 (快速路徑) 模式範例

  • 對於整個內容:

    [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization)]
    [JsonSerializable(typeof(WeatherForecast))]
    internal partial class SerializeOnlyContext : JsonSerializerContext
    {
    }
    
  • 對於個別的類型:

    [JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Serialization)]
    internal partial class SerializeOnlyWeatherForecastOnlyContext : JsonSerializerContext
    {
    }
    
  • 完整的程式範例

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

中繼資料型模式範例

  • 對於整個內容:

    [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);
    
  • 對於個別的類型:

    [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);
    
  • 完整的程式範例

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

ASP.NET Core 的來源產生支援

在 Blazor 應用程式中,使用採用來源產生內容或 TypeInfo<TValue>HttpClientJsonExtensions.GetFromJsonAsyncHttpClientJsonExtensions.PostAsJsonAsync 擴充方法多載。

從 .NET 8 開始,您也可以使用接受來源產生內容或 TypeInfo<TValue>HttpClientJsonExtensions.GetFromJsonAsAsyncEnumerable 擴充方法多載。

在 Razor Pages、MVC、Azure SignalR Service 和 Web API 應用程式中,使用 JsonSerializerOptions.TypeInfoResolver 屬性來指定內容。

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

在 Razor Pages、MVC、Azure SignalR Service 和 Web API 應用程式中,使用 JsonSerializerOptions.TypeInfoResolver 屬性來指定內容。

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

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

在 Razor Pages、MVC、Azure SignalR Service 和 Web API 應用程式中,使用 JsonSerializerOptionsAddContext 方法,如下列範例所示:

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

注意

非同步序列化不支援 JsonSourceGenerationMode.Serialization 或快速路徑序列化。

在 .NET 7 和舊版中,這項限制也適用於接受 StreamJsonSerializer.Serialize 同步多載。 從 .NET 8 開始,即使串流序列化需要中繼資料型模型,但如果已知承載夠小而符合預先決定的緩衝區大小,則會回復為快速路徑。 如需詳細資訊,請參閱https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#json

停用反映預設值

因為 System.Text.Json 預設會使用反映,因此呼叫基本序列化方法可能會中斷原生 AOT 應用程式,而原生 AOT 應用程式不支援所有必要的反映 API。 這些中斷可能很難診斷出來,因為它們可能無法預測,且應用程式通常會使用 CoreCLR 執行階段進行偵錯,其中反映可正常運作。 相反地,如果您明確停用反映型序列化,則中斷會更容易診斷出來。 使用反映型序列化的程式碼會導致在執行階段擲回具有描述性訊息的 InvalidOperationException

若要停用應用程式中的預設反映,請將專案檔中的 JsonSerializerIsReflectionEnabledByDefault MSBuild 屬性設定為 false

<PropertyGroup>
  <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup>
  • 不論執行階段、CoreCLR 或 原生 AOT,此屬性的行為都是一致的。
  • 如果您未指定此屬性,且已啟用 PublishTrimmed,則系統會自動停用反映型序列化。

您可以使用 JsonSerializer.IsReflectionEnabledByDefault 屬性,以程式設計方式檢查反映是否停用。 下列程式碼片段示範如何根據是否啟用反映來設定序列化程式:

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

由於屬性會被視為連結時間常數,因此上一個方法不會將在原生 AOT 中所執行應用程式中的反映型解析程式設定為根目錄。

指定選項

在 .NET 8 和更新版本中,您可以使用 JsonSerializerOptions 設定的大部分選項也可以使用 JsonSourceGenerationOptionsAttribute 屬性來設定。 透過屬性設定選項的優點是在編譯時間指定組態,這可確保產生的 MyContext.Default 屬性已使用所有相關選項集預先設定。

下列程式碼示範如何使用 JsonSourceGenerationOptionsAttribute 屬性來設定選項。

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

使用 JsonSourceGenerationOptionsAttribute 指定序列化選項時,請呼叫下列其中一個序列化方法:

  • 採用 TypeInfo<TValue>JsonSerializer.Serialize 方法。 傳遞您內容類別的 Default.<TypeName> 屬性:

    jsonString = JsonSerializer.Serialize(
        weatherForecast, SerializationModeOptionsContext.Default.WeatherForecast);
    
  • 採用內容的 JsonSerializer.Serialize 方法。 傳遞您內容類別的 Default 靜態屬性。

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

若呼叫的方法允許您在自己的 Utf8JsonWriter 執行個體中傳遞,便會接受寫入器的 Indented 設定,而不是 JsonSourceGenerationOptionsAttribute.WriteIndented 選項。

若是利用呼叫採用 JsonSerializerOptions 執行個體的建構函式來建立和使用內容執行個體,將會使用提供的執行個體,而不是 JsonSourceGenerationOptionsAttribute指定的選項。

以下是上述範例在完整程式中的樣貌:

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

使用 JsonSerializerOptions 指定選項

無法使用 JsonSourceGenerationOptionsAttribute 來設定 JsonSerializerOptions 的一些選項。 若要使用 JsonSerializerOptions 指定選項:

  • 建立 JsonSerializerOptions 的執行個體。
  • 建立衍生自 JsonSerializerContext的類別執行個體,再將 JsonSerializerOptions 執行個體傳遞給建構函式。
  • 呼叫採用內容執行個體或 TypeInfo<TValue>JsonSerializer 的序列化或還原序列化方法。

緊接在下列範例內容類別之後,是序列化和還原序列化範例程式碼:

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

以下是完整程式中的上述範例:

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

合併來源產生器 (部分機器翻譯)

您可以在單一 JsonSerializerOptions 執行個體內結合多個來源產生內容中的合約。 使用 JsonSerializerOptions.TypeInfoResolver 屬性來鏈結已使用 JsonTypeInfoResolver.Combine(IJsonTypeInfoResolver[]) 方法結合的多個內容。

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

從 .NET 8 開始,如果您稍後想要在前面加上或附加另一個內容,則可以使用 JsonSerializerOptions.TypeInfoResolverChain 屬性來執行此動作。 鏈結的順序相當重要:JsonSerializerOptions 會查詢每個解析程式的順序,並傳回非 uull 的第一個結果。

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.

TypeInfoResolverChain 屬性所做的任何變更會由 TypeInfoResolver 反映,反之亦然。

將列舉欄位序列化為字串

根據預設,會將列舉序列化為數字。 若要在使用來源產生時將特定列舉的欄位序列化為字串,請使用 JsonStringEnumConverter<TEnum> 轉換器標註它。 或者,若要設定所有列舉的地毯式原則,請使用 JsonSourceGenerationOptionsAttribute 屬性。

JsonStringEnumConverter<T> 轉換器

若要使用來源產生將列舉名稱序列化為字串,請使用 JsonStringEnumConverter<TEnum> 轉換器。 (原生 AOT 執行階段不支援非泛型 JsonStringEnumConverter 類型。)

使用 JsonConverterAttribute 屬性,以 JsonStringEnumConverter<TEnum> 轉換器標註列舉型別:

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
}

建立 JsonSerializerContext 類別,並使用 JsonSerializableAttribute 屬性標註它:

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

下列程式碼會將列舉名稱序列化,而不是數值:

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 類似下列範例:

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

地毯式原則

您可以套用地毯式原則以使用 JsonSourceGenerationOptionsAttribute 來將列舉序列化為字串,而不是使用 JsonStringEnumConverter<TEnum> 型別。 建立 JsonSerializerContext 類別,並使用 JsonSerializableAttributeJsonSourceGenerationOptionsAttribute 屬性標註它:

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

請注意,列舉沒有 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
}

另請參閱