我們在開發供跨系統使用的資料交換服務時,通常我們會使用各系統都通用的資料格式,較常見的有Xml, Json等,
而相較於Xml,我更喜歡資料結構精簡的Json,它在資料量大時還可以減少傳輸所消耗的頻寬。
除了常用的Open Source Library Json.Net之外,其實在.Net Framework中就已經內建有將Class序列化為Json格式的Library,今天要介紹的就是其中之一的JavaScriptSerializer。
前言
我們在開發供跨系統使用的資料交換服務時,
通常我們會使用各系統都通用的資料格式,較常見的有Xml, Json等,
而相較於Xml,我更喜歡資料結構精簡的Json,
它在資料量大時還可以減少傳輸所消耗的頻寬。
除了常用的Open Source Library Json.Net之外,
其實在.Net Framework中就已經內建有將Class序列化為Json格式的Library,
今天要介紹的就是其中之一的JavaScriptSerializer。
使用JavaScriptSerializer序列化Entity
其實JavaScriptSerializer的使用方法非常的簡單,
我們先定義好我們的Data Entity如下
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime Birthday { get; set; }
public int Age { get; set; }
public string Introduction { get; set; }
public string Comment { get; set; }
public Department Department { get; set; }
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
我們可以產生一組資料
var person = new Person()
{
ID = 1,
Name = "Kirk",
Birthday = new DateTime(1985, 6, 8),
Age = 26,
Introduction = "Sample",
Department = new Department()
{
ID = 2,
Name = "Geomatic"
}
};
再使用JavaScriptSerializer來序列化這組資料
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.Serialize(person);
我們就可以輕鬆地得到Json格式的資料,如下
是不是十分的輕鬆又簡單呢?
繼承JavaScriptConverter擴充JavaScriptSerializer
從上段之中,我們可以發現因為我們資料中的Person的Comment屬性和Department的Description屬性是null,
這是因為我在產生資料的時候,並沒有塞資料到那兩個屬性之中,
所以JavaScriptSerializer會自動用null來表示該屬性是空的。
那如果今天我有一個需求是如果string是空值時,就不要顯示該屬性在Json之中,那又該怎麼辦呢?
我們可以自己實作JavaScriptConverter,定義自己所預期的Serialize方法,
然後透過JavaScriptSerializer的RegisterConverters方法,
將自己定義JavaScriptConvert註冊到JavaScriptSerializer之中就可以了!
首先我們繼承JavaScriptConverter來實做自己的序列化方法
public class IgnoreEmptyStringJavaScriptConverter : JavaScriptConverter
{
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
Dictionary<string, object> result = new Dictionary<string, object>();
Type objectType = obj.GetType();
// 透過Reflection取得屬性資訊
foreach (var propertyInfo in objectType.GetProperties())
{
// 取得屬性值
var propertyValue = propertyInfo.GetValue(obj, null);
// 若屬性為字串,且為空值,忽略它不序列化
if (propertyInfo.PropertyType == typeof(string))
{
if ((propertyValue == null || string.IsNullOrEmpty(propertyValue.ToString())))
{
continue;
}
}
result.Add(propertyInfo.Name, propertyValue);
}
return result;
}
public override IEnumerable<Type> SupportedTypes
{
get { return new Type[] { typeof(Person), typeof(Department) }; }
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
// Deserializer Method
}
}
在我們覆寫的Serialize方法中,他回傳的是一個IDictionary格式的資料集,
而其實JavaScriptSerializer也是透過Dictionary中的Key Value Pair來做Json的轉換,
所以若要達到我們的需求,忽略屬性是空字串的話,
其實只要在屬性為空時,不將他加入Dictionary之中就可以了。
而另外一個要注意的是SupprotedTypes屬性,
它代表的意義是會透過這個JavaScriptConverter的資料型態有哪些,
若Entity的Type並不存在SupportedTypes的資料集中,
則JavaScriptSerializer會使用預設的JavaScriptConverter來轉換,
所以我們必須將Person和Department的型別加入其中。
在使用時,只需多一個步驟將JavaScriptConveter註冊到JavaScriptSerializer之中即可
JavaScriptSerializer serializer = new JavaScriptSerializer();
// 註冊自定義的JavaScriptConverter
serializer.RegisterConverters(new JavaScriptConverter[]{
new IgnoreEmptyStringJavaScriptConverter()
});
serializer.Serialize(person);
即可得到結果
就可以發現我們得到的資料已經符合我們的需求了
結語
在需求簡單的時候,我們其實可以透過內建的JavaScriptSerializer來轉換Json格式,
除了JavaScriptSerializer之外,其實.Net還有一個DataContractJsonSerializer,
甚至是Open Source中註明的Json.Net,當然也可以實做屬於自己的JsonSerializer,
其實每一種的實作方式都不盡相同,大家可以選擇自己慣用且熟悉的來使用囉!
最後推薦一個Chrome在開發Json好用的Extension: JSONView,
使用效果就如同本文圖片中囉!
若有任何問題也歡迎大家多多指教與討論 :)
參考資料: