原貼地址:http://bbs.zkinfo.com/thread-80510-1-1.html
最近要用到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
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 { get; set; }
public
string UserName { get; set; }
public DateTime Birthday { get; set; }
}
///
<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":"http://Date(378662400000+0800)//","UserId":1,"UserName":"張三"},{"Birthday":"http://Date(412876800000+0800)//","UserId":2,"UserName":"李四"},{"Birthday":"http://Date(446918400000+0800)//","UserId":3,"UserName":"王五"}]
jQuery調用JSON代碼:
jQuery調用
<script type="text/javascript">
$().ready(function() {
$.getJSON("Demo.ashx", function(data) {
var msg = [data.length];
for (var i in data) {
msg =
"UserId:"
+ data .UserId +
",UserName:"
+ data .UserName +
",Birthday:"
+ data .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":"http://Date(378662400000+0800)//","<UserId>k__BackingField":1,"<UserName>k__BackingField":"張三"},{"<Birthday>k__BackingField":"http://Date(412876800000+0800)//","<UserId>k__BackingField":2,"<UserName>k__BackingField":"李四"},{"<Birthday>k__BackingField":"http://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;}
}
完整DEMO下載: JSONDemo.rar
最近要用到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 { get; set; }
public
string UserName { get; set; }
public DateTime Birthday { get; set; }
}
///
<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":"http://Date(378662400000+0800)//","UserId":1,"UserName":"張三"},{"Birthday":"http://Date(412876800000+0800)//","UserId":2,"UserName":"李四"},{"Birthday":"http://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 =
"UserId:"
+ data .UserId +
",UserName:"
+ data .UserName +
",Birthday:"
+ data .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":"http://Date(378662400000+0800)//","<UserId>k__BackingField":1,"<UserName>k__BackingField":"張三"},{"<Birthday>k__BackingField":"http://Date(412876800000+0800)//","<UserId>k__BackingField":2,"<UserName>k__BackingField":"李四"},{"<Birthday>k__BackingField":"http://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;}
}
完整DEMO下載: JSONDemo.rar
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
