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

.NET6中JSON与枚举映射:EnumMemberAttribute失效问题及解决方案

问题:.NET6 System.Text.Json 无法识别EnumMemberAttribute进行枚举反序列化

问题原因

.NET6自带的JsonStringEnumConverter默认不支持EnumMemberAttribute,它仅基于枚举成员的名称(支持大小写不敏感匹配)进行序列化/反序列化,不会读取EnumMemberAttribute指定的自定义值。因此当JSON中出现NOT_AVAILABLE时,无法映射到标记了[EnumMember(Value = "NOT_AVAILABLE")]的NotAvailable枚举值,最终抛出反序列化异常。

无外部库的解决方案

自定义一个支持EnumMemberAttribute的JSON枚举转换器,替代默认的JsonStringEnumConverter:

1. 创建自定义转换器类

public class JsonStringEnumMemberConverter<TEnum> : JsonConverter<TEnum> where TEnum : struct, System.Enum
{
    private readonly Dictionary<TEnum, string> _enumToString = new();
    private readonly Dictionary<string, TEnum> _stringToEnum = new();
    private readonly Dictionary<int, TEnum> _numberToEnum = new();

    public JsonStringEnumMemberConverter()
    {
        var type = typeof(TEnum);

        foreach (var value in Enum.GetValues<TEnum>())
        {
            var enumMember = type.GetMember(value.ToString())[0];
            var attr = enumMember.GetCustomAttributes(typeof(EnumMemberAttribute), false)
              .Cast<EnumMemberAttribute>()
              .FirstOrDefault();

            _stringToEnum.Add(value.ToString(), value);
            var num = Convert.ToInt32(type.GetField("value__")?
                    .GetValue(value));
            if (attr?.Value != null)
            {
                _enumToString.Add(value, attr.Value);
                _stringToEnum.Add(attr.Value, value);
                _numberToEnum.Add(num, value);
            }
            else
            {
                _enumToString.Add(value, value.ToString());
            }
        }
    }

    public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var type = reader.TokenType;
        if (type == JsonTokenType.String)
        {
            var stringValue = reader.GetString() ?? "";
            if (_stringToEnum.TryGetValue(stringValue, out var enumValue))
            {
                return enumValue;
            }
        }
        else if (type == JsonTokenType.Number)
        {
            var numValue = reader.GetInt32();
            _numberToEnum.TryGetValue(numValue, out var enumValue);
            return enumValue;
        }

        return default;
    }

    public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(_enumToString[value]);
    }
}

2. 在枚举属性上使用自定义转换器

修改实体类中的枚举属性,替换原来的JsonStringEnumConverter为自定义转换器:

private enum Status {
    Open,
    Closed,
    
    [EnumMember(Value = "NOT_AVAILABLE")]
    NotAvailable
}
    
private class MyJson {

    [JsonPropertyName("user_name")]
    public string UserName {get; set;} = string.Empty;
    
    [JsonConverter(typeof(JsonStringEnumMemberConverter<Status>))]
    [JsonPropertyName("status")]
    public Status? Status {get; set;}
    
    public override string ToString() => $"{{UserName: {UserName}, Status: {Status}}}";
}

效果说明

该自定义转换器具备以下能力:

  • 识别枚举成员的EnumMemberAttribute值,实现自定义字符串与枚举值的双向映射
  • 支持字符串(包括枚举原名称和自定义值)、数字类型的JSON值反序列化
  • 序列化时优先输出EnumMemberAttribute指定的自定义值,无该属性则输出枚举原名称

内容的提问来源于stack exchange,提问作者grasbueschel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 16:31:17