如何用System.Text.Json将第三方枚举数组序列化为字符串数组?
使用System.Text.Json序列化第三方枚举数组为字符串值数组
问题背景
假设现有如下DTO:
public class FooDto { public string Bar { get; set; } public DayOfWeek[] Days { get; set; } }
需要将其序列化为符合API要求的JSON:
{ "bar": "someString", "days": ["Monday", "Friday", "Sunday"] }
但默认序列化结果会将枚举转为数值:
{ "bar": "someString", "days": [1, 5, 0] }
核心问题:如何用System.Text.Json将System.DayOfWeek这类第三方枚举数组序列化为字符串值数组,且不使用Newtonsoft.Json。
已尝试但无效的思路:
- 在数组属性上标注
[JsonConverter(typeof(JsonStringEnumConverter))]不生效 - 无法直接修改第三方枚举
DayOfWeek添加转换器特性 - 枚举不支持继承,无法创建代理类
- 自定义DTO并编写映射逻辑不够优雅
解决方案
方法一:全局配置JsonSerializerOptions(最简洁)
直接在序列化时配置JsonSerializerOptions,添加JsonStringEnumConverter并启用驼峰命名(匹配目标JSON格式),该配置会自动处理所有枚举类型(包括数组中的枚举元素):
var fooDto = new FooDto { Bar = "someString", Days = new[] { DayOfWeek.Monday, DayOfWeek.Friday, DayOfWeek.Sunday } }; var options = new JsonSerializerOptions { // 添加枚举转字符串的转换器 Converters = { new JsonStringEnumConverter() }, // 启用驼峰命名,匹配目标JSON的属性名格式 PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; string json = JsonSerializer.Serialize(fooDto, options);
序列化结果完全符合需求:
{ "bar": "someString", "days": ["Monday", "Friday", "Sunday"] }
方法二:自定义针对DayOfWeek[]的JsonConverter
如果只需要针对特定的枚举数组属性处理,而非全局配置,可以自定义转换器:
public class DayOfWeekArrayConverter : JsonConverter<DayOfWeek[]> { private readonly JsonStringEnumConverter _enumConverter = new JsonStringEnumConverter(); public override DayOfWeek[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartArray) throw new JsonException("JSON token is not an array."); var dayList = new List<DayOfWeek>(); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndArray) break; // 复用JsonStringEnumConverter处理单个枚举元素的反序列化 var day = (DayOfWeek)_enumConverter.Read(ref reader, typeof(DayOfWeek), options); dayList.Add(day); } return dayList.ToArray(); } public override void Write(Utf8JsonWriter writer, DayOfWeek[] value, JsonSerializerOptions options) { writer.WriteStartArray(); foreach (var day in value) { // 复用JsonStringEnumConverter处理单个枚举元素的序列化 _enumConverter.Write(writer, day, options); } writer.WriteEndArray(); } }
然后在DTO的属性上标注该转换器(同时记得配置驼峰命名):
public class FooDto { public string Bar { get; set; } [JsonConverter(typeof(DayOfWeekArrayConverter))] public DayOfWeek[] Days { get; set; } } // 序列化时配置驼峰命名 var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; string json = JsonSerializer.Serialize(fooDto, options);
说明
方法一的全局配置方式最为简洁,无需额外编写自定义转换器,且能统一处理所有枚举类型的序列化/反序列化;方法二则适用于仅需针对特定枚举数组属性做特殊处理的场景。
内容的提问来源于stack exchange,提问作者Yekt
相关产品推荐
相关产品推荐

