JavaScriptSerializer序列化和反序列化JSON:使用自定義JavaScriptConverter


JSON的序列化和反序列化已經成為Web開發必不可少的知識。現在常用的有System.Web.Script.Serialization下的JavaScriptSerializer來進行處理;另外一個比較常用且高效的類庫是JSON.NET。

在開發一些小的應用時,由於想盡量較少項目的依賴,所以不太願意使用JSON.NET。JavaScriptSerializer基本上能滿足簡單的需求,但當一個屬性要序列化成別的名字時,就顯得力不從心了。還有就是可能業務需要,某些屬性不希望在某一個條件下進行序列化。鑒於上面的業務需要,我們就需要自定義一個JavaScriptConverter。

自定義JavaScriptConverter的使用流程:

  • 定義一個JavaScriptConverter,指明期支持的類型。
  • 在序列化方法調用前注冊該轉換器。

顯然,這兩個步驟都不是很麻煩。我們舉一個具體的業務環境來說明:在ExtJS的TreePanel控件中,TreeNode的屬性有id、text等,其中如果checked屬性存在,則屬性結果顯示節點選擇框。在C#中,checked是關鍵字,所以不能定義為屬性,TreeNode的C#代碼如下:

    public class TreeNode
    {
        public string id { get; set; }
        public string text { get; set; }
        public bool? isChecked { get; set; }
        public List<TreeNode> children { get; set; }
    }

我將checked屬性映射到類中的isChecked字段,該字段可以有三個狀態:null、true和false,當為null的時候,將不會序列化該字段,前台也不會顯示節點選擇框。

現在要實現一個TreeNodeJSConverter,代碼如下:

    public class TreeNodeJSConverter : JavaScriptConverter
    {
        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            TreeNode node = new TreeNode();

            object value = null;
            if (dictionary.TryGetValue("id", out value))
                node.id = (string)value;
            if (dictionary.TryGetValue("text", out value))
                node.text = (string)value;
            if (dictionary.TryGetValue("children", out value))
            {
                if (value != null && value.GetType() == typeof(ArrayList))
                {
                    var list = (ArrayList)value;
                    node.children = new List<TreeNode>();

                    foreach (Dictionary<string, object> item in list)
                    {
                        node.children.Add((TreeNode)this.Deserialize(item, type, serializer));
                    }
                }
                else
                {
                    node.children = null;
                }
            }
            return node;
        }

        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            var node = obj as TreeNode;
            if (node == null)
                return null;
            if(!string.IsNullOrEmpty(node.id))
            dic.Add("id", node.id);
            if (!string.IsNullOrEmpty(node.text))
            dic.Add("text", node.text);
            if (node.isChecked.HasValue)
                dic.Add("checked", node.isChecked.Value);
            if (node.children != null)
            dic.Add("children", node.children);

            return dic;
        }

        public override IEnumerable<Type> SupportedTypes
        {
            get
            {
                return new Type[] { typeof(TreeNode) };
            }
        }
    }

代碼討論:TreeNodeJSConverter類首先需要繼承JavaScriptConverter,然后實現它的相關方法:Deserialize、Serialize和SupportedTypes,分別是反序列化、序列化和支持的類型。

在序列化方法Serialize中,我們需要將屬性添加到一個字典結構中,就可以完成序列化的工作了。具體要序列化那些字段還是要判斷一下相應的值是否存在。

在反序列化方法Deserialize中,字典結構存放着相應的值,當值存在的時候就可以為TreeNode相應的字段賦值。比較麻煩的事children屬性,因為其為嵌套的List類型,而JSON中的數組結構會被轉化成ArrayList結構,所以我們只需要遞歸的循環ArrayList中的每一個項,將其轉換為TreeNode就可以了。

最后是SupportedTypes字段,返回支持的類型,我們這里顯示的返回TreeNode的類型。

 

定義好了轉換器之后,我們需要為在序列化的時候注冊該轉換器即可:

        public static string SerializeToJson(object obj)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new JavaScriptConverter[] { new TreeNodeJSConverter() });

            return serializer.Serialize(obj);
        }

        public static T DeserializeJson<T>(string jsonString)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            serializer.RegisterConverters(new JavaScriptConverter[] { new TreeNodeJSConverter() });

            return serializer.Deserialize<T>(jsonString);
        }

代碼中標紅的部分就是注冊轉化器的地方,用起來很方便,代碼都貼出來了,不再提供源碼下載了。。親,早點睡吧!


免責聲明!

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



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