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 等判断。

从上到下,主要只讲解了一个问题,字里行间语言上都有很多的不严谨。不多知识方法是相同的,代码全部贴上,希望对大家有所帮助。谢谢。

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

时间: 2024-08-25 03:44:59

Newtonsoft.Json高级用法之枚举中文转义的相关文章

再谈Newtonsoft.Json高级用法

上一篇Newtonsoft.Json高级用法发布以后收到挺多回复的,本篇将分享几点挺有用的知识点和最近项目中用到的一个新点进行说明,做为对上篇文章的补充. 阅读目录 动态改变属性序列化名称 枚举值序列化问题 全局设置 总结 回到顶部 动态改变属性序列化名称 "动态改变属性序列化名称"顾名思义:在不同场景下实体字段序列化后字段名称不同,比如有下面实体A,正常序列化后json为{"Id":"123"} public class A { public

Newtonsoft.Json高级用法

手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数据,经过分析一个简单的列表接口每一行数据返回了16个字段,但是手机APP端只用到了其中7个字段,剩余9个字段的数据全部都是多余的,如果接口返回数据为40K大小,也就是说大约20K的数据为无效数据,3G网络下20K下载差不多需要1s,不返回无效数据至少可以节约1s的时间,大大提高用户体验.本篇将为大家

Newtonsoft.Json 高级用法

基本用法 Json.NET是支持序列化和反序列化DataTable,DataSet,Entity Framework和Entity的.下面分别举例说明序列化和反序列化. DataTable: //序列化DataTable DataTable dt = new DataTable(); dt.Columns.Add("Age", Type.GetType("System.Int32")); dt.Columns.Add("Name", Type.G

Newtonsoft.Json高级用法--转载至 焰尾迭 随笔

本人只做搬运工,以这方便自己学习的态度!以下内容均为拷贝! 如有不适请联系本人! 本文原作者:焰尾迭 本文地址:http://www.cnblogs.com/yanweidie/p/4605212.html#commentform 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数据,经过分析一个简单的列表接口每一行数据返回了16个字段,但是手机A

【Json】Newtonsoft.Json高级用法

手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数据,经过分析一个简单的列表接口每一行数据返回了16个字段,但是手机APP端只用到了其中7个字段,剩余9个字段的数据全部都是多余的,如果接口返回数据为40K大小,也就是说大约20K的数据为无效数据,3G网络下20K下载差不多需要1s,不返回无效数据至少可以节约1s的时间,大大提高用户体验.本篇将为大家

转:Newtonsoft.Json高级用法

原文地址:http://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数据,经过分析一个简单的列表接口每一行数据返回了16个字段,但是手机APP端只用到了其中7个字段,剩余9个字段的数据全部都是多余的,如果接口返回数据为40K大小,也就是说大约20K的数据为无效数据

Newtonsoft.Json高级用法 1.忽略某些属性 2.默认值的处理 3.空值的处理 4.支持非公共成员 5.日期处理 6.自定义序列化的字段名称

手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数据,经过分析一个简单的列表接口每一行数据返回了16个字段,但是手机APP端只用到了其中7个字段,剩余9个字段的数据全部都是多余的,如果接口返回数据为40K大小,也就是说大约20K的数据为无效数据,3G网络下20K下载差不多需要1s,不返回无效数据至少可以节约1s的时间,大大提高用户体验.本篇将为大家

【转】 Newtonsoft.Json高级用法

手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数据,经过分析一个简单的列表接口每一行数据返回了16个字段,但是手机APP端只用到了其中7个字段,剩余9个字段的数据全部都是多余的,如果接口返回数据为40K大小,也就是说大约20K的数据为无效数据,3G网络下20K下载差不多需要1s,不返回无效数据至少可以节约1s的时间,大大提高用户体验.本篇将为大家

Newtonsoft.Json高级用法(转载)

http://www.cnblogs.com/yanweidie/p/4605212.html#!comments 数据字典生成工具之旅系列文章导航