You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 22:15:01