.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
相关产品推荐
相关产品推荐

