如何在 System.Text.Json 中使用源生成
System.Text.Json 中的源生成在 .NET 6 及更高版本中提供。 在应用中使用时,应用的语言版本必须为 C# 9.0 或更高版本。 本文介绍如何在应用中使用源生成支持的序列化。
有关不同源生成模式的信息,请参阅源生成模式。
使用源生成默认值
若要将源生成用于所有默认值(两种模式,默认选项):
创建一个从 JsonSerializerContext 派生的分部类。
通过向上下文类应用 JsonSerializableAttribute 来指定要序列化或反序列化的类型。
调用 JsonSerializer 方法:
- 采用 JsonTypeInfo<T> 实例,或
- 采用 JsonSerializerContext 实例,或
- 采用 JsonSerializerOptions 实例,并且已将其 JsonSerializerOptions.TypeInfoResolver 属性设置为上下文类型的
Default
属性(.NET 7 及更高版本)。
默认情况下,如果未指定源生成模式,则会使用这两种源生成模式。 若要了解如何指定要使用的模式,请参阅本文后面的 指定源生成模式。
下面是以下示例中使用的类型:
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
{
}
无需使用 [JsonSerializable]
属性显式指定 WeatherForecast
成员的类型。 声明为 object
的成员是此规则的例外。 需要指定声明为 object
的成员的运行时类型。 例如,假设有以下类:
public class WeatherForecast
{
public object? Data { get; set; }
public List<object>? DataList { get; set; }
}
你知道,在运行时,它可能有 boolean
和 int
对象:
WeatherForecast wf = new() { Data = true, DataList = new List<object> { true, 1 } };
其次,必须将 boolean
和 int
声明为 [JsonSerializable]
:
[JsonSerializable(typeof(WeatherForecast))]
[JsonSerializable(typeof(bool))]
[JsonSerializable(typeof(int))]
public partial class WeatherForecastContext : JsonSerializerContext
{
}
若要指定集合的源生成,请将 [JsonSerializable]
与集合类型一起使用。 例如:[JsonSerializable(typeof(List<WeatherForecast>))]
。
使用源生成的 JsonSerializer
方法
在以下示例中,上下文类型的静态 Default
属性提供具有默认选项的上下文类型的实例。 上下文实例提供返回 JsonTypeInfo<WeatherForecast>
实例的 WeatherForecast
属性。 可以使用 [JsonSerializable]
特性的 TypeInfoPropertyName 属性为此属性指定其他名称。
序列化示例
使用 JsonTypeInfo<T>:
jsonString = JsonSerializer.Serialize(
weatherForecast!, SourceGenerationContext.Default.WeatherForecast);
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), SourceGenerationContext.Default);
sourceGenOptions = new JsonSerializerOptions
{
TypeInfoResolver = SourceGenerationContext.Default
};
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), sourceGenOptions);
反序列化示例
使用 JsonTypeInfo<T>:
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
jsonString, SourceGenerationContext.Default.WeatherForecast);
weatherForecast = JsonSerializer.Deserialize(
jsonString, typeof(WeatherForecast), SourceGenerationContext.Default)
as WeatherForecast;
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"}
}
}
}
指定源生成模式
可以为完整上下文指定基于元数据的模式或序列化优化模式,其中可能包括多个类型。 也可以为单个类型指定模式。 如果同时执行这两项操作,则类型的模式规范将优先。
- 对于完整上下文,请使用 JsonSourceGenerationOptionsAttribute.GenerationMode 属性。
- 对于单个类型,请使用 JsonSerializableAttribute.GenerationMode 属性。
序列化优化(快速路径)模式示例
对于完整上下文:
[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":25,"Summary":"Hot"} } } }
ASP.NET Core 中的源生成支持
在 Blazor 应用中,使用 HttpClientJsonExtensions.GetFromJsonAsync 和 HttpClientJsonExtensions.PostAsJsonAsync 扩展方法(采用源生成上下文或 TypeInfo<TValue>
)的重载。
从 .NET 8 开始,你还可以使用接受源生成上下文或 TypeInfo<TValue>
的 HttpClientJsonExtensions.GetFromJsonAsAsyncEnumerable 扩展方法的重载。
在 Razor Pages、MVC、SignalR 和 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、SignalR 和 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、SignalR 和 Web API 应用中,使用 AddContext 方法 JsonSerializerOptions,如以下示例所示:
[JsonSerializable(typeof(WeatherForecast[]))]
internal partial class MyJsonContext : JsonSerializerContext { }
services.AddControllers().AddJsonOptions(options =>
options.JsonSerializerOptions.AddContext<MyJsonContext>());
注意
异步序列化不支持 JsonSourceGenerationMode.Serialization(快速路径序列化)。
在 .NET 7 及更早版本中,此限制也适用于接受 Stream 的 JsonSerializer.Serialize 的同步重载。 从 .NET 8 开始,即使流式处理序列化需要基于元数据的模型,但如果已知有效负载足够小,预定的缓冲区大小足够容纳,则它将回退到快速路径。 有关详细信息,请参阅 https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-8/#json。
禁用反射默认值
由于 System.Text.Json 默认使用反射,因此调用基本序列化方法可能会中断本机 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 中运行的应用程序中对基于反射的解析程序进行 root 操作。
指定选项
在 .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
实例传递给构造函数。 - 调用
JsonSerializer
的序列化或反序列化方法(采用上下文实例或TypeInfo<TValue>
)。
下面是一个示例上下文类,后跟序列化和反序列化示例代码:
[JsonSerializable(typeof(WeatherForecast))]
internal partial class OptionsExampleContext : JsonSerializerContext
{
}
jsonString = JsonSerializer.Serialize(
weatherForecast,
typeof(WeatherForecast),
new OptionsExampleContext(
JsonSerializerOptions.Web));
weatherForecast = JsonSerializer.Deserialize(
jsonString,
typeof(WeatherForecast),
new OptionsExampleContext(
JsonSerializerOptions.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(
JsonSerializerOptions.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(
JsonSerializerOptions.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 按其指定顺序查询每个解析程序,并返回非 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.
对 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 类,并使用 JsonSerializableAttribute 和 JsonSourceGenerationOptionsAttribute 特性对其进行注释:
[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
}
自定义枚举成员名称
从 .NET 9 开始,可以使用 JsonStringEnumMemberName 属性自定义枚举成员名称。 有关详细信息,请参阅自定义枚举成员名称。