如何让POST请求体支持传入Enum枚举的Description属性值作为参数
实现方案
核心思路是自定义JSON反序列化转换器,在解析枚举字段时优先匹配Description特性标注的文本。以下是.NET生态下两种主流JSON序列化组件的实现方式:
通用枚举Description获取扩展方法
先写一个通用扩展方法用来读取枚举值上的Description特性内容,后续两种转换器都可以复用:
using System.ComponentModel; using System.Reflection; public static class EnumExtensions { // 获取枚举值对应的Description文本 public static string GetDescription(this Enum enumValue) { FieldInfo fieldInfo = enumValue.GetType().GetField(enumValue.ToString()); DescriptionAttribute[] attributes = fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[]; return attributes != null && attributes.Length > 0 ? attributes[0].Description : enumValue.ToString(); } // 根据Description文本反向匹配枚举值 public static T GetEnumFromDescription<T>(string description) where T : Enum { foreach (var field in typeof(T).GetFields()) { if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute) { if (attribute.Description.Equals(description, StringComparison.OrdinalIgnoreCase)) return (T)field.GetValue(null); } // 兼容直接传枚举本身名称的场景 if (field.Name.Equals(description, StringComparison.OrdinalIgnoreCase)) return (T)field.GetValue(null); } throw new ArgumentException($"未找到匹配描述'{description}'的枚举值{typeof(T).Name}", nameof(description)); } }
System.Text.Json 实现(.NET Core 3.0+ 默认使用)
自定义枚举转换器:
using System.Text.Json; using System.Text.Json.Serialization; public class DescriptionEnumConverter<T> : JsonConverter<T> where T : Enum { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { string description = reader.GetString(); return EnumExtensions.GetEnumFromDescription<T>(description); } // 兼容直接传枚举数值的场景 if (reader.TokenType == JsonTokenType.Number) { int enumValue = reader.GetInt32(); return (T)Enum.ToObject(typeof(T), enumValue); } throw new JsonException($"无法解析值为{reader.GetString()}的枚举类型{typeof(T).Name}"); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { // 序列化时输出Description友好名称 writer.WriteStringValue(value.GetDescription()); } }
转换器注册(二选一即可)
- 全局注册:所有对应枚举类型字段都会生效
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new DescriptionEnumConverter<PaymentMethodType>()); // 其他需要支持的枚举可继续添加 });
- 仅指定字段生效:给对应属性加特性即可
public class TransactionPaymentDetailRequest { [JsonConverter(typeof(DescriptionEnumConverter<PaymentMethodType>))] public PaymentMethodType? MethodType { get; set; } }
Newtonsoft.Json 实现
如果项目仍使用Newtonsoft.Json作为序列化组件,自定义转换器如下:
using Newtonsoft.Json; public class DescriptionEnumConverter<T> : JsonConverter where T : Enum { public override bool CanConvert(Type objectType) { // 兼容可空枚举类型 return objectType == typeof(T) || Nullable.GetUnderlyingType(objectType) == typeof(T); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { string description = reader.Value.ToString(); return EnumExtensions.GetEnumFromDescription<T>(description); } if (reader.TokenType == JsonToken.Integer) { int enumValue = Convert.ToInt32(reader.Value); return Enum.ToObject(typeof(T), enumValue); } throw new JsonSerializationException($"无法解析值为{reader.Value}的枚举类型{typeof(T).Name}"); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value is Enum enumValue) { writer.WriteValue(enumValue.GetDescription()); return; } writer.WriteNull(); } }
转换器注册(二选一即可)
- 全局注册:
builder.Services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.Converters.Add(new DescriptionEnumConverter<PaymentMethodType>()); });
- 仅指定字段生效:
public class TransactionPaymentDetailRequest { [JsonConverter(typeof(DescriptionEnumConverter<PaymentMethodType>))] public PaymentMethodType? MethodType { get; set; } }
配置完成后,传入payload中的"MethodType": "Credit Card"就会自动映射为PaymentMethodType.CreditCard,同时接口返回数据时也会自动输出Description标注的友好名称,而非枚举本身的字段名。
内容的提问来源于stack exchange,提问作者M0rty
相关产品推荐
相关产品推荐

