最近看博客園中 焰尾迭 的兩篇關於"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; } }
我們寫個測試看對不對:
結果如下:
總結
其實這里自定義實現了一個json自定義類型轉換。利用枚舉的Description特性利用反射實現枚舉中文轉義。其實這類轉義在我們平時開發過程中經常見到。用JsonConvert可以給我們帶來一定的解耦。
省去if esleif 等判斷。
從上到下,主要只講解了一個問題,字里行間語言上都有很多的不嚴謹。不過知識點涉及到Newtonsoft.Json的自定義類型轉換,反射等。代碼全部貼上,希望對大家有所幫助。謝謝。
再次感謝焰尾迭的分享。 謝謝!,同時也希望也能和你一樣被大家推薦。謝謝。