最近看博客园中 焰尾迭 的两篇关于"Newtonsoft.Json高级用法"的文章受到了很多人的评论,一度登入到头条推荐。
今天我就不再重复焰尾迭博文中的一些提过的Newtonsoft.Json的高级用法。大家如果想知道直接去看。
Newtonsoft.Json高级用法
再谈Newtonsoft.Json高级用法
我主要说焰尾迭 没有提到的用法——枚举中文转义
枚举值序列化问题(摘自焰尾迭 段落)
public enum NotifyType
{
/// <summary>
/// Emil发送 /// </summary> Mail=0, /// <summary> /// 短信发送 /// </summary> SMS=1 } public class TestEnmu { /// <summary> /// 消息发送类型 /// </summary> public NotifyType Type { get; set; } } JsonConvert.SerializeObject(new TestEnmu());
输出结果: 现在改造一下,输出"Type":"Mail"
public class TestEnmu
{
/// <summary>
/// 消息发送类型 /// </summary> [JsonConverter(typeof(StringEnumConverter))] public NotifyType Type { get; set; } }
其它的都不变,在Type属性上加上了JsonConverter(typeof(StringEnumConverter))表示将枚举值转换成对应的字符串,而StringEnumConverter是Newtonsoft.Json内置的转换类型,最终输出结果
思考
到这里StringEnumConverter确实为我们解决了很多问题,从枚举值类型转到名称。 如果我们是英国人该多好呀,到这里Newtonsoft.Json 自带的Converter已经为我们解决一切问题。
谁叫我们是中国人,到到枚举转成Mail还是很不爽。
如果能把枚举转成”电子邮箱“才符合我们中国人的习惯。
{ "Type":"电子邮箱" }
枚举值中文序列化
首先根据上面的目标我们首先改造下我们的枚举类型
public enum NotifyType { /// <summary> /// 电子邮箱 /// </summary> [Description("电子邮箱")] Mail = 0, /// <summary> /// 手机短信 /// </summary> [Description("手机短信")]
SMS = 1
}
接下来我们自定义一个EnumJsonConvert 类,考虑到我们枚举可能会传入不同类型,我们这里使用泛型
public class EnumJsonConvert<T>:JsonConverter where T: struct, IConvertible { public void EnumConverter() { if (!typeof (T).IsEnum) { throw new ArgumentException("T 必须是枚举类型"); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } try { return reader.Value.ToString(); } catch (Exception ex) { throw new Exception(string.Format("不能将枚举{1}的值{0}转换为Json格式.", reader.Value, objectType)); } } /// <summary> /// 判断是否为Bool类型 /// </summary> /// <param name="objectType">类型</param> /// <returns>为bool类型则可以进行转换</returns> public override bool CanConvert(Type objectType) { return true; } public bool IsNullableType(Type t) { if (t == null) { throw new ArgumentNullException(nameof(t)); } return t.BaseType != null && (t.BaseType.FullName == "System.ValueType" && t.GetGenericTypeDefinition() == typeof(Nullable<>)); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } string bValue = value.ToString(); int isNo; if (int.TryParse(bValue, out isNo)) { bValue= GetEnumDescription(typeof(T), isNo); } else { bValue= GetEnumDescription(typeof(T), value.ToString()); } writer.WriteValue(bValue); } /// <summary> /// 获取枚举描述 /// </summary> /// <param name="type">枚举类型</param> /// <param name="value">枚举名称</param> /// <returns></returns> private string GetEnumDescription(Type type, string value) { try { FieldInfo field = type.GetField(value); if (field == null) { return ""; } var desc = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; if (desc != null) return desc.Description; return ""; } catch { return ""; } } /// <summary> /// 获取枚举描述 /// </summary> /// <param name="type">枚举类型</param> /// <param name="value">枚举hasecode</param> /// <returns></returns> private string GetEnumDescription(Type type, int value) { try { FieldInfo field = type.GetField(Enum.GetName(type, value)); if (field == null) { return ""; } var desc = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; if (desc != null) return desc.Description; return ""; } catch { return ""; } } }
到这里我们自定义的JsonConvert已经实现好了。开始使用吧。
我们定义一个类Myclass
public class MyClass { public string UserName { get; set; } [JsonConverter(typeof(EnumJsonConvert<NotifyType>))] // 这里就是 我们特殊的地方 public int NotifyType { get; set; } }
我们写个测试看对不对:
结果如下: 我们实现了最初的目标,一般我们数据库到保存着枚举的值类型,比如这里的 0,1,2,3……。 我们前端一般需要显示我们的语言,比如这里的电子邮箱,手机短信……
总结
其实这里自定义实现了一个json自定义类型转换。利用枚举的Description特性利用反射实现枚举中文转义。其实这类转义在我们平时开发过程中经常见到。用JsonConvert可以给我们带来一定的解耦。
省去if esleif 等判断。
从上到下,主要只讲解了一个问题,字里行间语言上都有很多的不严谨。不过知识点涉及到Newtonsoft.Json的自定义类型转换,反射等。代码全部贴上,希望对大家有所帮助。谢谢。
再次感谢焰尾迭的分享。 谢谢!,同时也希望也能和你一样被大家推荐。谢谢。