.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对象的数组

image

image

image

在火狐里面看是这样的

image

image

 

 

如果是在.net 3.5里面使用自带的JavaScriptSerializer 进行序列化,那么返回的数据,是 json 字符串,需要在前台用 js的 eval 或者$.parseJSON 转换成json对象

image

在火狐看是这样的

image

 

image

在火狐看是这样的

image

同样的数据,在.net 2.0里面,使用 Json.net 进行json 序列化之后,返回的也是 json字符串,并且通过 json.net序列化的时间,是有点问题的

image

在火狐里面是

image 

image

 

那么这些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 />
&nbsp;<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; }

    }
}
posted @ 2012-11-26 17:24  梨花驿路  阅读(2731)  评论(0编辑  收藏  举报