.net中对象序列化技术浅谈

  • 2009-03-11

    阅读2756评论2
    序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数 据。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。反之,反序列化根据流重新构造对象。此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件 中“恢复”对象到序列化之前的状态。在.net中有提供了几种序列化的方式:二进制序列化XML序列化SOAP序列化
     
    二进制序列化所谓二进制序列化,指的是对象序列化之后是二进制形式的。二进制序列化是通过BinaryFormatter类来实现的,这个类位于System.Runtime.Seria2lization.Formatters.Binary命名空间下。
    XML序列化所谓XML序列化,是指对象序列化之后的结果是XML形式的。保存XML序列化是通过XmlSerializer 类来实现的, 这个类位于System.Xml.Serialization命名空间下。
    SOAP序列化所谓SOAP序列化是指对象序列化之后的结果符合SOAP协议,也就是可以通过SOAP 协议传输(不知道SOAP协议?百度一下吧)。SOAP序列化是通过SoapFormatter类来实现的,这个类位于 System.Runtime.Serialization.Formatters.Soap命名空间下,并且需要注意需要手动添加对这个命名空间的引 用,如下图所示: 
    下面编写一个类用于序列化和反序列化,这个类的代码如下:
    下面是分别用上面的三个类进行序列化和反序列化的代码:
    这个程序的运行效果如下: 可 见通过上面三个类都能实现将对象序列化保存,并且都能反序列化还原到对象被序列化之前的状态(这正是序列化意义所在,能保存对象运行时的状态并且还能还 原)。如果运行上面的代码会在C盘根目录下创建三个文件,分别是MyObject.dat、MyObject.soap和MyObject.xml文件, 因为MyObject.dat是二进制文件,所以无法查看文件的内容,但是我们可以打开MyObject.soap和MyObject.xml这两个文件 来比较一下有什么区别。MyObject.soap文件的后缀虽然是.soap,但是还是可以用记事本打开的,下面是MyObject.soap文件的内容:MyObject.xml文件也可以用记事本打开,它的内容如下:
    熟悉SOAP协议的朋友一看MyObject.soap文件的内容就知道它符合SOAP协议,MyObject.xml文件毫无疑问是一个符合XML规范的文件。
    对代码作几点说明:1、如果采用BinaryFormatter类或者SoapFormatter类来实现序列化,则一定要给类加上Serializable属性,如代码中所示:如果不给要序列化的对象加上这个属性,那么采用采用BinaryFormatter类或者SoapFormatter类来实现序列化时会报异常,但使用XmlSerializer 类序列化对象时可以不用这个属性。2、另外,如果不想序列化某个字段,可以给其加上NonSerialized属性,这样在序列化时就不会保存这个这个字段的值了,比如不想序列化name这个字段,可以如下写代码:
    再次运行刚才的程序会得到如下效果: 看有黄色底线部分,因为name字段不被序列化,所以通过二进制序列化和SOAP序列化之后再反序化就得不到原来的值了。3、最后还需要说明一点的是,SoapFormatter类在.net3.5开始已经过时了,微软建议使用BinaryFormatter类来序列化和反序列化了。
     
    Llllllllllll⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
    使用Json.NET来序列化所需的数据

    我们在做开发的时候,很多时候需要和Json数据格式打交道,如Web开发里面,很多时候,数据通过Json进行传递到页面上,然后在进行处理的。而使用Json的时候,我们很多时候会涉及到几个序列化对象的使用:DataContractJsonSerializer,JavaScriptSerializer 和Json.NET。大多数人都会选择性能以及通用性较好Json.NET,这个不是微软的类库,但是一个开源的世界级的Json操作类库,从下面的性能对比就可以看到它的其中之一的性能优点。
    Json.NET能很好序列化或者反序列化.NET的各种类型数据,而且它的另一个优点,是可以配置Attribute属性,指定输出的属性的名称或者是否输出,这点我非常喜欢。
    JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的数据交换格式。JSON是“名值对”的集合。结构由大括号'{}',中括号'[]',逗号',',冒号':',双引号'“”'组成,包含的数据类型有Object,Number,Boolean,String,Array, NULL等。
    1、在Web中使用Json数据
     在我的基于MVC+EasyUI的Web开发框架中,Web界面层大量使用了Ajax方式获取所需数据,然后绑定到树列表控件或者其他界面控件里面,在前面的一些Web框架随笔系列里面,我介绍过很多Json格式的操作。
    如在MVC的视图里面,通过Web请求的Json数据后初始化树控件的代码如下所示
    //初始化组织机构列表
    functioninitDeptTreeview() { $("#loading").show(); $('#treeDept').tree({ url: '/User/GetMyDeptTreeJson?userId=@Session["UserId"]', onClick: function(node) { loadDataByOu(node.id); } }); $("#loading").fadeOut(500); }
    或者用户角色的初始化界面代码
    $('#lbxRoles').empty(); $.getJSON("/Role/GetRolesByUser?r=" + Math.random() + "&userid=" + info.ID, function(json) { $.each(json, function(i, item) { $('#lbxRoles').append('<option value="' + item.ID + '">' + item.Name + '</option>'); }); });
    前面说过,Json.NET具有属性配置功能,可以指定某个属性是否输出,或者输出的名称转义等。默认情况下,Json.Net序列化后结果中的字段名称和类中属性的名称一致,如果想自定义序列化后的字段名称,可以使用JsonProperty。
    我们知道,EasyUI的Tree控件里面,它的数据格式,除了一个id和text是必须的之外,它的很多属性是可选的,也就是说在Json里面,可以不输出某个属性的内容。这个通过配置
    [JsonProperty( NullValueHandling = NullValueHandling.Ignore)]
    就可以忽略某个属性的输出了,如果这个属性的值为null的话。
    树控件的数据还有一个checked属性, 如果没有转义功能,我们需要指定属性为checked, 而checked是C#里面的保留关键字,不能使用,那么就没办法了。而Json.NET提供了转义功能的配置Attribute,很好解决问题,如下所示。
    [JsonProperty(PropertyName = "checked", NullValueHandling =NullValueHandling.Ignore)] publicbool? Checked { get; set; }
    因此整个EasyUI的Tree数据对象信息,在C#里面可以定义为如下所示(这里可以忽略DataContract、DataMember的定义)。
    ///<summary>
    ///定义EasyUI树的相关数据,方便控制器生成Json数据进行传递 ///</summary>
    [DataContract] [Serializable] publicclassEasyTreeData { ///<summary>
    ///ID ///</summary>
    [DataMember] publicstringid { get; set; } ///<summary>
    ///节点名称 ///</summary>
    [DataMember] publicstringtext { get; set; } ///<summary>
    ///是否展开 ///</summary>
    [JsonProperty(NullValueHandling =NullValueHandling.Ignore)] [DataMember] publicstringstate { get; set; } ///<summary>
    ///图标样式 ///</summary>
    [DataMember]
    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    publicstringiconCls { get; set; }
    [JsonProperty(PropertyName = "checked", NullValueHandling =NullValueHandling.Ignore)] [DataMember(Name="checked")] publicbool? Checked { get; set; } ///<summary>
    ///子节点集合 ///</summary>
    [DataMember] publicList<EasyTreeData> children { get; set; }
    使用上的实体类,并使用Json.NET来序列化我们的数据,我们可能得到下面的Json数据。
    [ { id: "-1", text: "无", state: "open"
    ,
    checked: true,
    children: [ ] }, { id: 
    "6", text: "总经办", state: "open", iconCls: "icon-group", children: [ ] } ]
    我们从上面的Json数据可以看到,Checked属性顺利转换为checked的名称属性,标记为[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] ,而值为null的属性,将不会出现在Json的字符串里面了。
    这个在某种情形下,正好就是我们所需要的。 
    2、在微信接口开发中使用Json
    微信API的接口,大量使用了Json数据,不仅很多返回的数据是使用Json表达,而且其Post的数据,也多数使用Json数据格式,如在我的前两篇随笔《C#开发微信门户及应用(5)--用户分组信息管理》 、《C#开发微信门户及应用(4)--关注用户列表及详细信息管理
    里面介绍的内容,微信的很多接口都使用了Json数据。
    如返回关注者列表的Json数据,就是如下所示。
    {"total":2,"count":2,"data":{"openid":["","OPENID1","OPENID2"]},"next_openid":"NEXT_OPENID"}
    创建用户分组,返回的数据格式如下,同样也是Json数据。
    { "group": { "id": 107, "name": "test"
    } }
    通过下面基于Json.NET的Json数据的转换,就可以顺利从Json字符串转换为相应的实体对象了。
    /// <summary>
    /// Json字符串操作辅助类
    /// </summary>
    public class JsonHelper<T> where T : class, new() { /// <summary>
    /// 检查返回的记录,如果返回没有错误,或者结果提示成功,则不抛出异常
    /// </summary>
    /// <param name="content">返回的结果</param>
    /// <returns></returns>
    private static bool VerifyErrorCode(string content) { if(content.Contains("errcode")) { ErrorJsonResult errorResult = JsonConvert.DeserializeObject<ErrorJsonResult>(content); //非成功操作才记录异常,因为有些操作是返回正常的结果({"errcode": 0, "errmsg": "ok"})
    if(errorResult != null&& errorResult.errcode !=ReturnCode.请求成功) { string error = string.Format("微信请求发生错误!错误代码:{0},说明:{1}", (int)errorResult.errcode, errorResult.errmsg); LogTextHelper.Error(errorResult); thrownewWeixinException(error);//抛出错误
    } } returntrue; } /// <summary>
    /// 转换Json字符串到具体的对象
    /// </summary>
    /// <param name="url">返回Json数据的链接地址</param>
    /// <returns></returns>
    public static T ConvertJson(string url) { HttpHelper helper = newHttpHelper(); string content =helper.GetHtml(url); VerifyErrorCode(content); T result = JsonConvert.DeserializeObject<T>(content); returnresult; } }
    而如果要把对象转换为Json字符串格式的数据,那么代码也很简单。
    JsonConvert.SerializeObject(obj, Formatting.Indented);
     

    本文出自 “周公(周金桥)的专栏” 博客,请务必保留此出处http://zhoufoxcn.blog.51cto.com/792419/162943

    2012-05-12
    也就是可以通过SOAP协议传输(不知道SOAP协议?百度一下吧)哈哈,我还真不知道这是什么协议,只是听说过,结果真去百度一下才知道更多一些。哈哈。。。。。
     

.net中对象序列化技术浅谈的更多相关文章

  1. .net中对象序列化技术

    序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数据.例如,可以序列化一个对象,然后使用 HTTP 通过 Inte ...

  2. [技术]浅谈OI中矩阵快速幂的用法

    前言 矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中,矩阵的运算是数值分析领域的重要问题. 基本介绍 (该部分为入门向,非入门选手可以跳过) 由 m行n列元素排列成的矩形阵列.矩阵里的 ...

  3. 对kotlin和java中的synchronized的浅谈

    synchronized在java中是一个关键字,但是在kotlin中是一个内联函数.假如分别在java和kotlin代码锁住同一个对象,会发生什么呢,今天写了代码试了试.首先定义people类 12 ...

  4. C++ STL中的常用容器浅谈

    STL是C/C++开发中一个非常重要的模板,而其中定义的各种容器也是非常方便我们大家使用.下面,我们就浅谈某些常用的容器.这里我们不涉及容器的基本操作之类,只是要讨论一下各个容器其各自的特点.STL中 ...

  5. 开发技术--浅谈Python函数

    开发|浅谈Python函数 函数在实际使用中有很多不一样的小九九,我将从最基础的函数内容,延伸出函数的高级用法.此文非科普片~~ 前言 目前所有的文章思想格式都是:知识+情感. 知识:对于所有的知识点 ...

  6. 开发技术--浅谈python数据类型

    开发|浅谈python数据类型 在回顾Python基础的时候,遇到最大的问题就是内容很多,而我的目的是回顾自己之前学习的内容,进行相应的总结,所以我就不玩基础了,很多在我实际生活中使用的东西,我会在文 ...

  7. 开发技术--浅谈python基础知识

    开发|浅谈python基础知识 最近复习一些基础内容,故将Python的基础进行了总结.注意:这篇文章只列出来我觉得重点,并且需要记忆的知识. 前言 目前所有的文章思想格式都是:知识+情感. 知识:对 ...

  8. CSS属性中的display属性浅谈;

    首先我们要知道什么是块级元素和行内元素有什么区别: 承接上篇文章:(浅谈HTML和body标签) 块级元素:浏览器解析为独占一行的元素(例如:div.table.ul等.),浏览器会在该元素的前后显示 ...

  9. ASP.NET中Session的个人浅谈

    看到博客园的一个哥们写的面试经历,想到了面试中常问到的Session,一时手痒就谈下自己对Session的理解,这东西最开始在用户登录登出的时候用到过,后来一直没怎么用过,里面还是有很多知识点值得注意 ...

随机推荐

  1. Get the Uniqueid of Action Originate in the AMI

    [asterisk-users] Get the Uniqueid of Action Originate in the AMI Adolphe Cher-Aime acheraime at gmai ...

  2. SpringBean

    springBean  <bean id="user" class="..."/> 默认是单例的. 如果要改成多例的则<bean id=&qu ...

  3. hdu 3661 Assignments (贪心)

    Assignments Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. C# DataSet和DataTable详解

    1.C# DataSet和DataTable详解:http://www.cnblogs.com/top5/archive/2009/04/23/1441765.html 2.DataSet和DataT ...

  5. javascript 中break、 continue、函数不能重载

    在javascript中,break与continue有着显著的差别. 如果遇到break语句,会终止最内层循环,无论后面还有多少计算. 如果遇到continue,只会终止此次循环,后面的自循环依然执 ...

  6. Andorid开发学习---ubuntu 12.04下搭建超好用的安卓模拟器genymotion 安装卸载virtualbox 4.3

    什么是Genymotion? Genymotion是一套完整的工具,它提供了Android虚拟环境.它简直就是开发者.测试人员.推销者甚至是游戏玩家的福音. Genymotion支持Windows.L ...

  7. java核心知识点学习----重点学习线程池ThreadPool

    线程池是多线程学习中需要重点掌握的. 系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好的提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考 ...

  8. Log4j基本用法----日志级别

    基本使用方法: Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式.日志信息的优先级从高到低有ERROR.WARN.INFO.DEBUG,分别用来指定这条日志信 ...

  9. python 内置函数 map filter reduce lambda

    map(函数名,可遍历迭代的对象) # 列组元素全加 10 # map(需要做什么的函数,遍历迭代对象)函数 map()遍历序列得到一个列表,列表的序号和个数和原来一样 l = [2,3,4,5,6, ...

  10. 如何在命令行里运行python脚本

    python是一款应用非常广泛的脚本程序语言,谷歌公司的网页就是用python编写.python在生物信息.统计.网页制作.计算等多个领域都体现出了强大的功能.python和其他脚本语言如java.R ...