[C#] 使用JavasacriptSerializer序列化Entity為Json

我們在開發供跨系統使用的資料交換服務時,通常我們會使用各系統都通用的資料格式,較常見的有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格式的資料,如下

2011-07-28_220021

是不是十分的輕鬆又簡單呢?

 

繼承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);

即可得到結果

2011-07-28_222112

就可以發現我們得到的資料已經符合我們的需求了

 

結語

在需求簡單的時候,我們其實可以透過內建的JavaScriptSerializer來轉換Json格式,

除了JavaScriptSerializer之外,其實.Net還有一個DataContractJsonSerializer,

甚至是Open Source中註明的Json.Net,當然也可以實做屬於自己的JsonSerializer,

其實每一種的實作方式都不盡相同,大家可以選擇自己慣用且熟悉的來使用囉!

最後推薦一個Chrome在開發Json好用的Extension: JSONView

使用效果就如同本文圖片中囉!

若有任何問題也歡迎大家多多指教與討論 :)

 

參考資料:

  1. JavaScriptSerializer 類別
  2. DataContractJsonSerializer 類別
  3. JsonMe - 合約與類型分離的輕量級JSON映射類庫
  4. 使用JavaScriptSerializer進行JSON序列化