zoukankan      html  css  js  c++  java
  • Newtonsoft.Json高级用法之枚举中文转义

     最近看博客园中 焰尾迭 的两篇关于"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的自定义类型转换,反射等。代码全部贴上,希望对大家有所帮助。谢谢。

    再次感谢焰尾迭的分享。 谢谢!,同时也希望也能和你一样被大家推荐。谢谢。

     

     
  • 相关阅读:
    怎樣在不同DB環境生成其它DB的存儲過程
    XML之sql:column用法对性能影响
    XML之sql:variable性能比较
    环回链接服务器
    动态列名数据视图实现
    一起学习win8应用1构建我们的第一个应用
    linux 限制root SSH登陆和限制su
    nginx 直接在配置文章中设置日志分割
    linux建立ssh信任关系
    linux系统meminfo详解(待补充)
  • 原文地址:https://www.cnblogs.com/DomoYao/p/Json.html
Copyright © 2011-2022 走看看