ServiceStack枚举序列化问题:EnumMember属性未按预期生效
解决EnumMember属性序列化不生效的问题
看起来你遇到的核心问题是:你给枚举值添加了[EnumMember(Value = "...")]属性,但序列化时并没有输出指定的自定义值,而是枚举的默认名称。这通常是因为你使用的JSON序列化框架没有正确识别EnumMember属性,或者缺少对应的转换器配置。
下面分两种常见的序列化场景给出针对性解决方案:
场景1:使用Newtonsoft.Json(Json.NET)
如果你的项目用的是经典的Newtonsoft.Json库,只需要启用StringEnumConverter,它会自动读取EnumMember的Value值。
方法1:序列化时指定配置
var jsonSettings = new JsonSerializerSettings { // 添加StringEnumConverter,确保只输出字符串而非整数 Converters = { new StringEnumConverter { AllowIntegerValues = false } } }; // 序列化示例 Day today = Day.Monday; string json = JsonConvert.SerializeObject(today, jsonSettings); // 输出结果:"MONDAY"
方法2:给枚举标记全局转换器
直接在枚举类上添加转换器属性,后续序列化该枚举时会自动生效:
[DataContract] [JsonConverter(typeof(StringEnumConverter))] public enum Day { [EnumMember(Value = "MONDAY")] Monday, [EnumMember(Value = "TUESDAY")] Tuesday, // ... 其他枚举值 }
场景2:使用System.Text.Json(.NET Core 3.0+ 默认)
如果你的项目用的是.NET Core/.NET 5+自带的System.Text.Json,默认不识别EnumMember属性,需要自定义转换器或命名策略。
方法1:自定义EnumMember转换器
写一个通用转换器来处理枚举的EnumMember属性:
public class EnumMemberJsonConverter<TEnum> : JsonConverter<TEnum> where TEnum : struct, Enum { public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { string value = reader.GetString(); // 遍历枚举字段匹配EnumMember的Value foreach (FieldInfo field in typeof(TEnum).GetFields()) { if (field.GetCustomAttribute<EnumMemberAttribute>() is EnumMemberAttribute attr && attr.Value == value) { return (TEnum)field.GetValue(null); } } // 匹配失败时回退到默认枚举解析 return Enum.Parse<TEnum>(value); } public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) { FieldInfo field = value.GetType().GetField(value.ToString()); EnumMemberAttribute attr = field?.GetCustomAttribute<EnumMemberAttribute>(); // 优先输出EnumMember的Value,无匹配则输出默认名称 writer.WriteStringValue(attr?.Value ?? value.ToString()); } }
序列化时配置该转换器:
var jsonOptions = new JsonSerializerOptions(); jsonOptions.Converters.Add(new EnumMemberJsonConverter<Day>()); Day today = Day.Monday; string json = JsonSerializer.Serialize(today, jsonOptions); // 输出结果:"MONDAY"
方法2:自定义命名策略(.NET 7+)
如果你使用的是.NET 7及以上版本,可以通过自定义命名策略简化实现:
public class EnumMemberNamingPolicy : JsonNamingPolicy { public override string ConvertName(string name) { var field = typeof(Day).GetField(name); var enumMemberAttr = field?.GetCustomAttribute<EnumMemberAttribute>(); return enumMemberAttr?.Value ?? name; } }
配置序列化选项:
var jsonOptions = new JsonSerializerOptions { Converters = { new JsonStringEnumConverter(new EnumMemberNamingPolicy()) } }; string json = JsonSerializer.Serialize(Day.Monday, jsonOptions); // 输出结果:"MONDAY"
最后建议你先确认项目中.ToJson()方法依赖的具体序列化库,再选择对应的方案解决问题。
内容的提问来源于stack exchange,提问作者LorneCash
相关产品推荐
相关产品推荐

