C#使用JSON.Net序列化Enum为含名称与数值键值对的实现问询
实现方案
步骤1:自定义枚举序列化转换器
继承Newtonsoft.Json的JsonConverter类,实现自定义序列化逻辑:
using Newtonsoft.Json; using System; public class EnumToNameValueConverter : JsonConverter { public override bool CanConvert(Type objectType) { // 只处理枚举类型 return objectType.IsEnum; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } Enum enumValue = (Enum)value; writer.WriteStartObject(); writer.WritePropertyName("name"); writer.WriteValue(enumValue.ToString()); writer.WritePropertyName("value"); writer.WriteValue(Convert.ToInt32(enumValue)); writer.WriteEndObject(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 如果不需要反序列化可以直接抛NotImplementedException,下面是基础反序列化实现 if (reader.TokenType == JsonToken.Null) { return null; } if (reader.TokenType == JsonToken.Integer) { return Enum.ToObject(objectType, reader.Value); } if (reader.TokenType == JsonToken.String) { return Enum.Parse(objectType, reader.Value.ToString()); } // 处理自定义的{name,value}结构反序列化 if (reader.TokenType == JsonToken.StartObject) { int value = 0; string name = null; while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName) { string propName = reader.Value.ToString(); reader.Read(); if (propName.Equals("value", StringComparison.OrdinalIgnoreCase)) { value = Convert.ToInt32(reader.Value); } else if (propName.Equals("name", StringComparison.OrdinalIgnoreCase)) { name = reader.Value.ToString(); } } else if (reader.TokenType == JsonToken.EndObject) { break; } } // 优先用数值反序列化,避免字符串拼写问题 return Enum.ToObject(objectType, value); } throw new JsonSerializationException("无法解析枚举类型"); } }
步骤2:使用转换器
有两种使用方式,按需选择即可:
方式1:指定单个属性使用转换器
给枚举类型的属性添加JsonConverter特性,仅对标记的属性生效:
public class Product { [JsonConverter(typeof(EnumToNameValueConverter))] public DisplayStatus displayStatus { get; set; } [JsonConverter(typeof(EnumToNameValueConverter))] public DrugClass drugClass { get; set; } [JsonConverter(typeof(EnumToNameValueConverter))] public DrugType drugType { get; set; } }
序列化逻辑保持原有写法即可:
string JSONOutput = JsonConvert.SerializeObject(product);
方式2:全局注册转换器,所有枚举都按此规则序列化
序列化时传入转换器参数,不需要给每个属性单独加特性:
string JSONOutput = JsonConvert.SerializeObject(product, new EnumToNameValueConverter());
说明
- 如果枚举是
Flags特性标记的位域枚举,name字段会自动返回多个枚举值用逗号分隔的拼接字符串,符合常规使用习惯 - 若不需要反序列化能力,可以删掉
ReadJson方法的实现,直接抛出NotImplementedException即可减少冗余代码
内容的提问来源于stack exchange,提问作者DIamondGeezer
相关产品推荐
相关产品推荐

