.net2.0和.net 3.5关于 json序列化的实现
关于json序列化,有3种解决方案
1:Json.NET (第三方组件,有.net 2.0版本和.net 3.5的版本)
2 :DataContractJsonSerializer (asp.net 3.5自带的序列化)
3:JavaScriptSerializer (asp.net 3.5自带的序列化)
先来看看.net 3.5的Json序列化
使用System.Web.Script.Serialization.JavaScriptSerializer类 (.net 3.5自带,.net 2.0无)
System.Web.Script.Serialization.JavaScriptSerializer类是.NET类库中自带的一种JSON序列化实现,在.NET Framework3.5及以后版本中可以使用这个类,这个类位于System.Web.Extensions.dll中,使用这个类是必须添加对这个dll的引用。
下面的代码是使用JavaScriptSerializer进行序列化和反序列化的例子:
public static void JavaScriptSerializerDemo() { User user =new User { UserId =1, UserName ="李刚", CreateDate = DateTime.Now.AddYears(-30), Birthday=DateTime.Now.AddYears(-50), Priority = Priority.Highest,
Salary =500000 }; //JavaScriptSerializer类在System.Web.Extensions.dll中,注意添加这个引用 JavaScriptSerializer serializer =new JavaScriptSerializer(); //JSON序列化 string result=serializer.Serialize(user); Console.WriteLine("使用JavaScriptSerializer序列化后的结果:{0},长度:{1}", result, result.Length); //JSON反序列化 user = serializer.Deserialize<User>(result); Console.WriteLine("使用JavaScriptSerializer反序列化后的结果:UserId:{0},UserName: {1},CreateDate:{2},Priority:{3}",
user.UserId, user.UserName, user.CreateDate, user.Priority); }
使用DataContractJsonSerializer类将类型实例序列化
为JSON字符串,并将JSON字符串反序列化为类型实例。 DataContractJsonSerializer在System.Runtime.Serialization.Json命名空间下
,.NET Framework 3.5包含在System.ServiceModel.Web.dll中,需要添加对其的引用;.NET Framework 4在System.Runtime.Serialization中。
然后在.net 2.0里面的 Json序列化
在.NET 2.0中没有内置序列化JSON的类,原因估计是当时Ajax尚未兴起。后来就有人写了一个Json.NET类库
下面是Json.NET , DataContractJsonSerializer 以及 JavaScriptSerializer 的支持特性对比
Json.NET | DataContractJsonSerializer | JavaScriptSerializer | |
Supports JSON | |||
Supports BSON | |||
Supports JSON Schema | |||
Supports .NET 2.0 | |||
Supports .NET 3.5 | |||
Supports .NET 4.0 | |||
Supports Silverlight | |||
Supports Windows Phone | |||
Supports WinRT | |||
Open Source | |||
MIT License | |||
LINQ to JSON (这个特性只有Json.NET才有) | |||
Thread Safe | |||
XPath-like JSON query syntax (类似xpath查询语法的JSON) | |||
Indented JSON support (缩进JSON支持) | |||
Efficient dictionary serialization (高效字典序列化) | |||
Nonsensical dictionary serialization | |||
Deserializes IList, IEnumerable, ICollection, IDictionary properties (反序列化IList,IEnumerable,ICollection,IDictionary属性) |
|||
Serializes circular references | |||
Supports serializing objects by reference | |||
Deserializes polymorphic properties and collections | |||
Serializes and deserializes multidimensional arrays | |||
Supports including type names with JSON | |||
Globally customize serialization process | |||
Supports excluding null values when serializing | |||
Supports SerializationBinder | |||
Conditional property serialization | |||
Includes line number information in errors | |||
Converts XML to JSON and JSON to XML (转换XML到JSON , 转换到JSON到XML) |
|||
JSON Schema validation (JSON模式验证) | |||
JSON Schema generation from .NET types | |||
Camel case JSON property names (驼峰式大小写JSON属性名) | |||
Non-default constructors support | |||
Serialization error handling (序列化错误处理) | |||
Supports populating an existing object | |||
Efficiently serializes byte arrays as base64 text | |||
Handles NaN, Infinity, -Infinity and undefined | |||
Handles JavaScript constructors | |||
Serializes .NET 4.0 dynamic objects | |||
Serializes ISerializable objects | |||
Supports serializing enums to their text name | |||
JSON recursion limit support | |||
Attribute property name customization | |||
Attribute property order customization | |||
Attribute property required customization | |||
Supports ISO8601 dates | |||
Supports JavaScript constructor dates | |||
Supports Microsoft AJAX dates | |||
Unquoted property names support | |||
Raw JSON support | |||
Supports reading and writing comments | |||
Serializes anonymous types | |||
Deserializes anonymous types | |||
Opt-in mode serialization | |||
Opt-out mode serialization | |||
Field (Serializable) mode serialization | |||
Efficiently stream reading and writing JSON | |||
Single or double quote JSON content | |||
Supports overriding a type's serialization | |||
Supports OnDeserialized, OnSerializing, OnSerialized and OnDeserializing attributes | |||
Supports serializing private properties | |||
DataMember attribute support | |||
MetdataType attribute support | |||
DefaultValue attribute support | |||
Serializes DataSets and DataTables | |||
Serailizes Entity Framework | |||
Serializes nHibernate | |||
Case-insensitive property deserialization |
下载 Json.NET 4.5 Release 11 (source + binary)
利用Jquery让返回的各类数据(string、集合(List<>)、类)以Json数据格式返回,为什么要用到result.d
这里我们顺带讲下Json
Json简单讲就是Javascript对象或数组.
Json形式一: javascript对象 { "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa" }
Json形式二: javascript数组 [{ "firstName": "Brett", "lastName":"McLaughlin", "email": "aaaa" },{ "firstName": "Jason", "lastName":"Hunterwang", "email": "bbbb"}]
当然javascript 数组和对象可以互相嵌套.如形式一中的"Brett"可以换成一个Js数组或Js对象.那微软的Ajax返回的是哪种形式呢.是第一种.
微软框架默认返回一个 { "d": "后台返回的数据" } 这里我们用以上示例中的测试到得比如
如上例的返回的是string类型的话Firefox调试如下
当返回的是List<>类型的话FireFox调试如下
返回的数据也是放在Js对象中的d属性里面 所以说这就是为什么我们老是用result.d来取微软的框架返回的数据.
在.net 3.5里面,如果是使用 linq直接把List<Product>进行返回的话,返回来的数据都是纯粹的json对象,而不是json字符串(区别就是 返回回来的数据的开头有没有 "" )
但是就算是返回的是 json的对象,也要仔细看看是返回的单个的json对象,还是json对象的数组
在火狐里面看是这样的
如果是在.net 3.5里面使用自带的JavaScriptSerializer 进行序列化,那么返回的数据,是 json 字符串,需要在前台用 js的 eval 或者$.parseJSON 转换成json对象
在火狐看是这样的
在火狐看是这样的
同样的数据,在.net 2.0里面,使用 Json.net 进行json 序列化之后,返回的也是 json字符串,并且通过 json.net序列化的时间,是有点问题的
在火狐里面是
那么这些json字符串前台,就需要通过 jquery的 函数,转换为 json对象,才可以正常的在前台通过 对象.productname 或者 对象.productid来访问
var jqueryjson = jQuery.parseJSON(result.d); //jQuery.parseJSON //$.parseJSON
接受一个JSON字符串,返回解析后的对象。
传入一个畸形的JSON字符串会抛出一个异常。
比如下面的都是畸形的JSON字符串: (正确的规律是,键值对,键必须是双引号,值可以双引号,也不可以不要双引号)
{test: 1} ( test 没有包围双引号)
{'test': 1} (使用了单引号而不是双引号)
另外,如果你什么都不传入,或者一个空字符串、null或undefined,parseJSON都会返回 null 。
把json字符串,转换为 json对象,或者直接使用 eval ,也是可以的
var dataObj=eval("("+result.d+")");//转换为json对象
下面是部分的代码,.net 3.5下用 linq 返回后台的数据,这种情况下,默认返回的json就是json对象,所以前台不用再 eval 来转换
前台 default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="web._Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function () { }) function showAll() { $.ajax({ type: "GET", //当前台ajax用get方式的时候,后台asmx页面的方法的UseHttpGet 必须为 true contentType: "application/json; charset=utf-8", url: "ProductService.asmx/GetAllProduct", dataType: "json", success: insertCallback, error: errorCallback }); } function showOne() { var idNumber = $("#txtId").val(); $.ajax({ type: "POST", //当前台ajax用post方式的时候,后台asmx页面的方法的UseHttpGet 必须为 false data: "{id:" + idNumber + ",tt:" + new Date().getTime() + "}", //这里传值和后台的必须一样或者是多余后台的参数列表,例如后台是id,这里也必须是id,但是我这里还是多传了一个值,代表刷新时间,防止有缓存 contentType: "application/json; charset=utf-8", url: "ProductService.asmx/GetByProductId", dataType: "json", success: insertCallback, error: errorCallback }); } function insertCallback(result) { alert(result.d); alert(typeof(result.d)); $('#productList > thead').empty(); $('#productList > tbody').empty(); //json返回来的数据默认就是 d if (result["d"] == null) {//如果result["d"] 为 null ,则表示没有查询到想对应的值 alert("没有数据"); return; } //清空原来的数据 $('#productList > thead:last').append('<tr><td>产品名称</td><td>价格</td><td>库存</td></tr>'); if (result["d"] != null && result["d"].length == undefined) { //既不是空,但是长度又是未定义,就表示只有1个值 $('#productList > tbody:last').append('<tr><td>' + result["d"].ProductName + '</td><td>' + result["d"].Price + '</td><td>' + result["d"].Stock + '</td></tr>'); } else { for (var i = 0; i < result["d"].length; i++) { var product = eval(result["d"][i]); $('#productList > tbody:last').append('<tr><td>' + product.ProductName + '</td><td>' + product.Price + '</td><td>' + product.Stock + '</td></tr>'); } } } function errorCallback(XMLHttpRequest, textStatus, errorThrown) { $('#productList > thead').empty(); $('#productList > tbody').empty(); alert(errorThrown + ':' + textStatus); } </script> </head> <body> <form id="form1" runat="server"> <div id="listContainer" class="container"> <div id="title"> <br /> <input id="btnAll" type="button" value="通过get方式显示所有的产品" onclick="showAll()" /><br /> <br /> <br> 请输入要搜索的产品ID :<input type="text" id="txtId"> <input id="btnOne" type="button" value="通过post方式显示1个产品" onclick="showOne()" /> </div> <table id="productList"> <thead> </thead> <tbody> </tbody> </table> </div> </form> </body> </html>
后台 ProductService.asmx , 没有使用序列化,而是直接返回 List<product> 类型,或者是 Product 类型,所以前台返回的是 json 对象,而不是json字符串
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; using System.Web.Script.Services; //如果想使用ScriptMethod,则必须引用此命名空间 namespace web { /// <summary> /// ProductService 的摘要说明 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] [System.ComponentModel.ToolboxItem(false)] // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 [System.Web.Script.Services.ScriptService] //这句话就是,如果你想在前台想用jquery或者是其他的ajax来调用下面的带有WebMethod的方法,那么这个注释就要去掉,问题是这个只有.net 3.5有,如果是.net 2.0呢?怎么解决? public class ProductService : System.Web.Services.WebService { private ProductData datasouuce //这里是一个属性 { get { return new ProductData(); } } /// <summary>获取所有的产品 /// /// </summary> /// <returns></returns> [WebMethod(Description = "获取所有的产品")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] //ResponseFormat:方法要返回的类型,一般为Json或者XML //UseHttpGet:true表示前台的ajax是通过“Get”可以访问此方法,如果通过POST,报错 //false表示前台的ajax是通过"post"来访问此方法,如果通过get,报错 public List<Product> GetAllProduct() { return datasouuce.GetAllProduct(); } /// <summary>根据产品ID,返回一个产品 /// /// </summary> /// <param name="id"></param> /// <returns></returns> [WebMethod(Description = "根据产品ID,返回一个产品")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = false)]//这里限制前台必须是post一个id过来,而不是get方式 public Product GetByProductId(string id) { return datasouuce.GetByProductId(Convert.ToInt32(id)); } /// <summary>根据价格,返回符合价格相同的产品列表 /// /// </summary> /// <param name="price"></param> /// <returns></returns> [WebMethod(Description="根据价格,返回符合价格相同的产品列表")] [ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)] public List<Product> GetByPrice(decimal price) { return datasouuce.GetByPrice(price); } } }
后台 ProductData.cs,定义了 产品的List,并且直接返回 List<product>或者是通过 linq 直接返回一个 product
using System; using System.Collections.Generic; using System.Web; using System.Linq; namespace web { public class ProductData { private List<Product> plist = new List<Product> { new Product(){ProductId=1,ProductName="笔记本", Price=10000, Stock=10}, new Product(){ProductId=2,ProductName="格子绒长袖衬衫", Price=90, Stock=20}, new Product(){ProductId=3,ProductName="纯棉长袖T恤", Price=99, Stock=40}, new Product(){ProductId=4,ProductName="炫彩T恤", Price=67, Stock=30}, new Product(){ProductId=5,ProductName="直筒裤男牛仔裤", Price=100, Stock=20}, new Product(){ProductId=6,ProductName="[无印严选]纯色V领长袖T恤", Price=67, Stock=50}, new Product(){ProductId=7,ProductName="英伦学院派马夹", Price=44, Stock=40}, new Product(){ProductId=8,ProductName="纯棉连帽宽松卫衣", Price=66, Stock=30}, new Product(){ProductId=9,ProductName="纯棉多口袋工装裤", Price=80, Stock=990}, new Product(){ProductId=10,ProductName="假两件长袖T恤", Price=89, Stock=30}, }; /// <summary>返回所有的产品 /// /// </summary> /// <returns></returns> public List<Product> GetAllProduct() { return plist; } /// <summary>根据产品ID,返回一个产品 /// /// </summary> /// <param name="id"></param> /// <returns></returns> public Product GetByProductId(int id) { return plist.FirstOrDefault(p => p.ProductId == id); } /// <summary>根据价格,返回符合价格相同的产品列表 /// /// </summary> /// <param name="price"></param> /// <returns></returns> public List<Product> GetByPrice(decimal price) { return plist.Where(p => p.Price == price).ToList(); } } }
如果是在 .net 3.5下,使用JavaScriptSerializer 来序列化,那么前台返回的还是 json字符串,那么前台获取值的时候,是需要 eval或者是jquery进行json转换的.
如果是在 .net 2.0的情况下,后台不能用 asms 来使用 webmethod给前台ajax调用,所以只能用 aspx.cs 里面写方法,并且给方法加 webmethod,并且写成静态方法给前台ajax调用,返回的json字符串
前台需要对json字符串,进行eval或者是jquery的json转换
后台 test.aspx.cs代码
using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using Newtonsoft.Json;// 这个json.net在.net 2.0的情况下给本身拓展支持Linq using System.Web.Services; namespace FanShe.Web { public partial class action : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } public static List<Product> plist = new List<Product> { new Product(){ProductId=1,ProductName="笔记本", Price=10000, Stock=10,AddTime=DateTime.Now}, new Product(){ProductId=2,ProductName="格子绒长袖衬衫", Price=90, Stock=20,AddTime=DateTime.Now}, new Product(){ProductId=3,ProductName="纯棉长袖T恤", Price=99, Stock=40}, new Product(){ProductId=4,ProductName="炫彩T恤", Price=67, Stock=30}, new Product(){ProductId=5,ProductName="直筒裤男牛仔裤", Price=100, Stock=20}, new Product(){ProductId=6,ProductName="[无印严选]纯色V领长袖T恤", Price=67, Stock=50}, new Product(){ProductId=7,ProductName="英伦学院派马夹", Price=44, Stock=40}, new Product(){ProductId=8,ProductName="纯棉连帽宽松卫衣", Price=66, Stock=30}, new Product(){ProductId=9,ProductName="纯棉多口袋工装裤", Price=80, Stock=990}, new Product(){ProductId=10,ProductName="假两件长袖T恤", Price=89, Stock=30}, }; [WebMethod] public static string ListToJson() { return JsonConvert.SerializeObject(plist); } [WebMethod] public static string Test() { //string temp = JsonConvert.SerializeObject(temp); return JsonConvert.SerializeObject(plist); } [WebMethod] public static string ToJson1() { var user = new { name = "jey", age = "18", address = "罗湖区田蜜路", mobile = new { telephone = "02784655336", ydmobile = "15871152147", dxmobile = "18036574142", ltmobile = "12365147893" }, }; return JsonConvert.SerializeObject(user); } [WebMethod] public static string ToJson1Array() { var user = new[]{ new { name = "joey1", age = "18", address = "罗湖区田蜜路", mobile = new { telephone = "02784655336", ydmobile = "15871152147", dxmobile = "18036574142", ltmobile = "12365147893" }, }, new { name = "joey2", age = "18", address = "罗湖区田蜜路", mobile = new { telephone = "02784655336", ydmobile = "15871152147", dxmobile = "18036574142", ltmobile = "12365147893" }, } }; return JsonConvert.SerializeObject(user); } [WebMethod] public static string ToJson2() { var result = new { hero = new { name = "zhouping", age = "16" }, user = new[] { new { name = "liudehua", age = "55" }, new { name = "zhm", age = "43" } } }; return JsonConvert.SerializeObject(result); } } [Serializable] public class Product { public long ProductId { get; set; }//产品ID public string ProductName { get; set; } public decimal Price { get; set; } public int Stock { get; set; }//产品储存量 public DateTime AddTime { get; set; } } }