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的自定义类型转换,反射等。代码全部贴上,希望对大家有所帮助。谢谢。

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

     

     
  • 相关阅读:
    HDU4474 Yet Another Multiple Problem BFS搜索
    HDU4473 Exam 数学分析
    2013ACM多校联合(4)
    POJ1273 网络流...
    HDU4472 Count 递推
    POJ1149 PIGS 网络流
    UVA10881 Piotr's Ants 想法题
    javascript js string.Format()收集
    修改 设置 vs.net 网站 调试 设为 起始页
    【转】HTML5杂谈 概念与现行游戏 割绳子 宝石迷阵
  • 原文地址:https://www.cnblogs.com/DomoYao/p/Json.html
Copyright © 2011-2022 走看看