.NET Framework 3.5中序列化成JSON數據及JSON數據的反序列化,以及jQuery的調用JSON

最近要用到jQuery調用JSON,但遇到幾個問題,正面將記錄下遇到的問題及解決方法。

在將Object序列化成JSON時普遍是使用以下幾種方式:

1. 第三方組件Newtonsoft.Json.dll來序列化。
2. 直接用StringBuilder拼接字符串。
3. .NET3.5中的DataContractJsonSerializer

很多人使用的是第三方組件來序列化,但.NET3.5中已經提供了對序列化及反序列化很好的支持,直接使用就行了,而拼接字符串的方式就更原始了,要對一些字符串進行處理也容易出錯。所以還是選擇了DataContractJsonSerializer,感覺非常方便。下面就看怎麼來實了:

首先創建項目,添加必要的程序集引用:System.ServiceModel.Web及System.Runtime.Serialization

創建ashx文件以便jQuery調用,當然也可以根據自己的需要創建WebServices或其它文件,代碼如下

Demo.ashx 


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Services;

namespace JSONDemo
{
    /// <summary>
    
/// $codebehindclassname$ 的摘要說明
    
/// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Demo : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            List<User> users = new List<User>();
            #region AddUser
            users.Add(new User
            {
                UserId = 1,
                UserName = "張三",
                Birthday = DateTime.Parse("1982/1/1")
            });
            users.Add(new User
            {
                UserId = 2,
                UserName = "李四",
                Birthday = DateTime.Parse("1983/2/1")
            });
            users.Add(new User
            {
                UserId = 3,
                UserName = "王五",
                Birthday = DateTime.Parse("1984/3/1")
            });
            #endregion
            string json = JsonHelper.Serialize(users);
            //context.Response.Write("序列化:/r/n");
            context.Response.Write(json);
            //User u = JsonHelper.Deserialize<User>("");
            List<User> users2 = JsonHelper.Deserialize<List<User>>(json);
            //context.Response.Write("/r/n反序列化:/r/n");
            foreach (User item in users2)
            {
                //context.Response.Write(string.Format("UserId:{0},UserName:{1},Birthday:{2}/r/n", item.UserId, item.UserName, item.Birthday));
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

    /// <summary>
    
/// 數據實體
    
/// </summary>
    //[Serializable]這裏是需要注意的地方
    public class User
    {
        public int UserId { getset; }
        public string UserName { getset; }
        public DateTime Birthday { getset; }
    }

    /// <summary>
    
/// JSON序列化與反序列化輔助類
    
/// </summary>
    public class JsonHelper
    {
        public static string Serialize<T>(T data)
        {
            System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(data.GetType());
            using (MemoryStream ms = new MemoryStream())
            {
                serializer.WriteObject(ms, data);
                return Encoding.UTF8.GetString(ms.ToArray());
                //ms.Position = 0;
                
//using (StreamReader sr = new StreamReader(ms))
                
//{
                
//    return sr.ReadToEnd();
                
//}
            }
        }

        public static T Deserialize<T>(string json)
        {
            T obj = Activator.CreateInstance<T>();
            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
            {
                System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(obj.GetType());
                return (T)serializer.ReadObject(ms);
            }
        }
    }
}

 

訪問Demo.ashx顯示結果如下,對了這就是我們想要的數據:

[{"Birthday":"//Date(378662400000+0800)//","UserId":1,"UserName":"張三"},{"Birthday":"//Date(412876800000+0800)//","UserId":2,"UserName":"李四"},{"Birthday":"//Date(446918400000+0800)//","UserId":3,"UserName":"王五"}]

 

jQuery調用JSON代碼:


<script type="text/javascript">
    $().ready(function() {
        $.getJSON("Demo.ashx", function(data) {
            var msg = [data.length];
            for (var i in data) {
                msg[i] = "UserId:" + data[i].UserId + ",UserName:" + data[i].UserName + ",Birthday:" + data[i].Birthday;
            }
            alert(msg.join('/n'));
        });
    });
</script>


但在實現時遇到幾個問題:
1. DateTime類型在實例化時如果未對DateTime屬性賦值序列化時(即:DateTime.MinValue)將會報錯:指定的參數已超出有效值的範圍。參數名: value 
在轉換爲 UTC 時大於 DateTime.MaxValue 或小於 DateTime.MinValue 的 DateTime 值無法系列化爲 JSON。]

根據提示是DateTime值小於DateTime.MinValue時造成的,但實際上未賦值時DateTime默認就是MinValue了,不存在小於MinValue。莫然其妙的一個問題,但如果DateTime值爲DateTime.MinValue.AddDays(1),就沒問題了。所以提示應該改成必須大於MinValue,不知道這算不算一個小BUG?

2. 當最開始序列化時發現雖然序列化的結果卻是下面這樣一堆字符:

 

[{"<Birthday>k__BackingField":"//Date(378662400000+0800)//","<UserId>k__BackingField":1,"<UserName>k__BackingField":"張三"},{"<Birthday>k__BackingField":"//Date(412876800000+0800)//","<UserId>k__BackingField":2,"<UserName>k__BackingField":"李四"},{"<Birthday>k__BackingField":"//Date(446918400000+0800)//","<UserId>k__BackingField":3,"<UserName>k__BackingField":"王五"}]

經查詢是因爲實體類聲明瞭可序列化造成的:
[Serializable]
public class User
當然把[Serializable]去掉,結果就正常了,可這樣實體類就不能實例化了?當然我們可以用其它方法來解決這一問題,用WCF中的數據契約聲明實體就行(別忘了在所有屬性上加上[DataMember]不然這些屬性都不可訪問哦。)[DataContract]
public class User
{
     [DataMember]
     public int UserId{get;set;}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章