如何全局处理项目中所有枚举的序列化与反序列化(无需逐个加转换器)
全局统一处理枚举的JSON序列化与反序列化方案
不管项目里有多少种枚举,只要全局配置一次自定义转换器,就能自动处理所有枚举的序列化和反序列化,不用再给每个枚举属性加特性。下面分两种常用JSON库给出具体实现:
使用Newtonsoft.Json(Json.NET)的全局配置
步骤1:自定义全局枚举转换器
先写一个通用的枚举转换器,继承JsonConverter<Enum>,实现序列化和反序列化逻辑:
public class GlobalEnumConverter : JsonConverter<Enum> { // 反序列化:把JSON值转成枚举 public override Enum ReadJson(JsonReader reader, Type objectType, Enum existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.Value is string enumString) { // 支持大小写不敏感转换 return (Enum)Enum.Parse(objectType, enumString, ignoreCase: true); } if (reader.Value is int enumInt) { return (Enum)Enum.ToObject(objectType, enumInt); } throw new JsonSerializationException($"没法把值 {reader.Value} 转成枚举 {objectType.Name}"); } // 序列化:把枚举转成JSON值(这里示例转成枚举名称,也可以改成数字) public override void WriteJson(JsonWriter writer, Enum value, JsonSerializer serializer) { writer.WriteValue(value.ToString()); } }
步骤2:全局注册转换器
在项目启动时注册这个转换器,所有枚举就会自动用它处理:
// ASP.NET Core 项目里这么配 services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.Converters.Add(new GlobalEnumConverter()); }); // 普通.NET项目里全局设置默认配置 JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = { new GlobalEnumConverter() } };
使用System.Text.Json的全局配置
System.Text.Json是.NET Core 3.0+内置的JSON库,用转换器工厂来全局处理所有枚举更方便:
步骤1:自定义枚举转换器工厂
public class GlobalEnumConverterFactory : JsonConverterFactory { // 判断是否支持转换枚举类型 public override bool CanConvert(Type typeToConvert) { return typeToConvert.IsEnum; } // 为每个枚举类型创建对应的转换器 public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { var converterType = typeof(GlobalEnumConverter<>).MakeGenericType(typeToConvert); return (JsonConverter)Activator.CreateInstance(converterType); } // 针对具体枚举类型的转换器实现 private class GlobalEnumConverter<TEnum> : JsonConverter<TEnum> where TEnum : struct, Enum { public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { if (Enum.TryParse(reader.GetString(), ignoreCase: true, out TEnum result)) { return result; } throw new JsonException($"没法把字符串 {reader.GetString()} 转成枚举 {typeToConvert.Name}"); } if (reader.TokenType == JsonTokenType.Number) { if (Enum.TryParse(reader.GetInt32().ToString(), out TEnum result)) { return result; } throw new JsonException($"没法把数字 {reader.GetInt32()} 转成枚举 {typeToConvert.Name}"); } throw new JsonException($"不支持用 {reader.TokenType} 类型的令牌转换枚举 {typeToConvert.Name}"); } public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) { // 这里把枚举序列化为名称,需要的话改成value.ToString("D")输出数字 writer.WriteStringValue(value.ToString()); } } }
步骤2:全局注册转换器工厂
// ASP.NET Core 项目里配置 services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new GlobalEnumConverterFactory()); // 可选:开启属性名称大小写不敏感,配合枚举反序列化 options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; }); // 普通.NET项目里使用 var jsonOptions = new JsonSerializerOptions(); jsonOptions.Converters.Add(new GlobalEnumConverterFactory()); // 序列化示例 string json = JsonSerializer.Serialize(YourTestEnum.ExampleValue, jsonOptions); // 反序列化示例 YourTestEnum enumVal = JsonSerializer.Deserialize<YourTestEnum>(json, jsonOptions);
额外说明
如果需要处理带[Description]特性的枚举(比如序列化时输出描述文本),只需要修改转换器里的Write方法,通过反射读取枚举字段的DescriptionAttribute值即可,全局配置一次就对所有枚举生效。
内容的提问来源于stack exchange,提问作者Sheo Kumar Pandey
相关产品推荐
相关产品推荐

