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的自定義類型轉換,反射等。代碼全部貼上,希望對大家有所幫助。謝謝。

再次感謝焰尾迭的分享。 謝謝!,同時也希望也能和你一樣被大家推薦。謝謝。

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM