System.Text.Json中如何为特定枚举字段回退默认转换器输出数值
特定枚举字段按底层数字类型序列化的实现方法
完全可以实现,无需修改字段的枚举类型,也不需要调整全局JSON序列化配置。System.Text.Json 对属性/字段显式标注的转换器有最高优先级,会覆盖全局配置的转换器规则。
实现步骤
- 编写通用的枚举转数字序列化转换器
这个转换器为全局适配,不需要为单个枚举重复编写逻辑,同时兼容普通枚举、可空枚举类型:
using System.Text.Json; using System.Text.Json.Serialization; public class EnumToNumberJsonConverter : JsonConverterFactory { public override bool CanConvert(Type typeToConvert) { // 匹配所有枚举类型(含可空枚举) return typeToConvert.IsEnum || (Nullable.GetUnderlyingType(typeToConvert)?.IsEnum == true); } public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { // 拆解可空枚举的实际类型 var enumType = Nullable.GetUnderlyingType(typeToConvert) ?? typeToConvert; // 实例化泛型内部转换器 var innerConverterType = typeof(InnerEnumNumberConverter<>).MakeGenericType(enumType); return (JsonConverter)Activator.CreateInstance(innerConverterType); } // 内部核心序列化逻辑 private class InnerEnumNumberConverter<TEnum> : JsonConverter<TEnum> where TEnum : struct, Enum { public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 从JSON数字值反序列化为枚举 if (reader.TokenType == JsonTokenType.Number) { var numericVal = reader.GetInt64(); return (TEnum)Enum.ToObject(typeof(TEnum), numericVal); } // 兼容字符串格式的数字值,避免反序列化报错 if (reader.TokenType == JsonTokenType.String && long.TryParse(reader.GetString(), out var strNumVal)) { return (TEnum)Enum.ToObject(typeof(TEnum), strNumVal); } throw new JsonException($"无法将当前值转换为枚举 {typeof(TEnum).Name}"); } public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) { // 序列化时直接输出枚举的底层数值,不做字符串转换 writer.WriteNumberValue(Convert.ToInt64(value)); } } }
- 在指定字段上应用转换器特性
只需要给需要按数字输出的枚举字段标注[JsonConverter]特性,其他字段不受任何影响,仍走全局的字符串枚举转换规则:
// 原有枚举定义保持不变 public enum OperationType : byte { Create = 0, Update = 1, Delete = 2 } public class OperationLog { public string LogContent { get; set; } // 该字段单独按底层byte类型输出JSON数字 [JsonConverter(typeof(EnumToNumberJsonConverter))] public OperationType OpType { get; set; } // 其余枚举字段正常走全局字符串转换规则,比如序列化为"Create"/"Update" public OperationType OriginOpType { get; set; } }
核心规则说明
System.Text.Json 的转换器优先级规则:属性/字段上通过
[JsonConverter]显式指定的转换器 > 全局配置中注册的转换器 > 框架内置默认转换器。
因此即使全局已经启用了JsonStringEnumConverter,标注了自定义数字转换器的字段也会完全绕开全局字符串转换逻辑,按数字类型输出,完全符合约束要求。
注意事项
- 全程不需要修改枚举本身定义,也不需要把字段类型改成byte/int,完全保留原有的强类型枚举属性
- 转换器自动支持可空枚举类型(比如
OperationType?),不需要额外适配 - 不会对全局配置、其他无特性标注的字段产生任何副作用
内容的提问来源于stack exchange,提问作者user1649304
相关产品推荐
相关产品推荐

