XML序列化与反序列化-程序员宅基地

技术标签: 序列化  反序列化  xml  .NET  

        XML序列化会将对象的公共属性、公有成员变量转化为xml格式流/文档,反序列化则从xml格式流/文档中将对象重构出来。xml序列化并不包含类型信息,不会序列化方法、私有变量、索引器等,如果要想序列化所有公有私有成员要使用DataContractSerializer。

        XmlSerializer类是进行XML序列化的最主要的类,其中最重要的两个函数是Serialize和Deserialize,分别负责序列化和反序列化。XmlSerializer类首先会创建C#文件,然后将这些文件编译成.dll文件,用这些.dll文件来执行序列化。

        如果有XML Schema,就可以使用XML Schema Definition工具来产生符合Schema规定类型的类,这样的类实例被序列化之后就符合该Schema规定。当然,.NET框架中可以使用XmlReader和XmlWriter类来解析和写入xml流。

        属性控制着由XmlSerializer类产生的XML流,这样就可以设置XML命名空间、元素名字、属性名字等。XmlSerializer还可以序列化对象使其产生符合SOAP规范的XML流。


XmlSerializer应用的安全考虑

  • XmlSerializer会创建很多c#文件,然后将它们编译成.dll文件(执行序列化),这些文件存放在TEMP目录中。但在创建和编译过程中,这些.cs和.dll易受恶意程序的攻击。(.NET4.0及以后版本通常是多用户共用TEMP目录,假如两个账户拥有不同的安全权限,高权限者运行使用了XmlSerializer的应用程就会出现危险。这种情况下,其他用户可能将.cs或.dll替换,就会破坏计算机的安全。)因而,确保每一个账户都有自己的profile。
  • 假如恶意用户发送了一个持续的XML数据流给web服务器,XmlSerializer就会持续产生数据直至计算机资源短缺。(如果应用程序运行在IIS环境中就可以避免这种情况的发生,因为IIS会过滤流,如果超过一定的大小就不处理,如果应用程序没有使用IIS,就要实现相似的功能,使XmlSerializer实现反序列化可以正常安全进行)。
  • XmlSerializer可以序列化任何被给类型的数据,运行任何代码。(恶意程序呈现威胁表现在两点:运行恶意代码,将恶意代码注入到XmlSerializer产生的c#文件中。前者可以通过代码访问安全性来阻止,后者的话谨记决不使用未知类型或不可信类型来序列化数据)。
  • 序列化的敏感数据可能易受攻击。(XmlSerializer序列化完数据之后,数据就存储在xml文件或其他形式数据存储。假如数据存储对其它进程可用,或Internet上可见,那么数据可能被恶意偷取和使用。)


可以被序列化的项:

  • public类的公有可读写属性和字段
  • 实现ICollection或者IEnumerable的类
  • XmlElement对象
  • XmlNode对象
  • DataSet对象


XML序列化的优势:

  • XmlSerializer类可以使我们在对对象进行xml序列化时,拥有完全灵活的控制。如果是创建xml web服务,就可以应用属性来控制类和成员的序列化,确保xml输出符合特定的Schema规范。
  • 对应用没有什么约束条件,只要产生的xml流符合给定的Schema规范即可。


XML序列化必须考虑的问题:

  • Sgen.exe工具是为了优化性能,专门设计出来用于产生系列化程序集的。
  • 序列化后的数据仅包含数据本身和类结构,类型和程序集信息都不会被包括进去。
  • 仅仅公有的属性和字段才可以被序列化,属性必须包含公有的get和set。
  • 要想被XmlSerializer序列化,类必须包含一个默认的构造函数。
  • 方法是不能被序列化的。
  • XmlSerializer可以处理满足特定要求的实现了IEnumerable或ICollection接口的类,特定要求如下:
    • 实现IEnumerable接口的类必须实现一个公有Add方法,带一个参数。而且参数必须同GetEnumerator()方法返回的IEnumerator的Current属性相一致。
    • 既实现了IEnumerabl接口又实现了ICollection接口的类,必须包含公有索引器(存储的每个集合元素有整型index,可以根据该index获取到数据项集合元素)、公有Count属性(集合元素的个数)。同样,Add函数必须要有,参数为从索引器获取到的数据类型或其基类。
    • 对于仅实现ICollection接口的类,被序列化的值从索引器获取而不是通过调用GetEnumerator。公有属性和字段都不会被序列化,除非公有字段返回了另一个实现了ICollection接口的类。
序列化:
  • 步骤:首先创建对象并设置公有字段和属性;然后构建一个XmlSerializer实例;最后调用Serialize函数产生XML流或文件。
  • class对象序列化:
    [Serializable]
    public class ObjectClass
    {
    	public ObjectClass ():this(0, null, 0.0f)
    	{
    	}
    	public ObjectClass(int age, string name, float salary)
    	{
    		Age = age;
    		Name = name;
    		_salary = salary;
    	}
    
    	public int Age;
    	public string Name;
    	private float _salary;//私有字段不会被序列化
    }
    Obj = new ObjectClass(6, "ha", 60);//obj为该类的公有字段,为其赋值
    StreamWriter sw = new StreamWriter("objClassXml.xml");//创建xml文件流
    XmlSerializer xs = new XmlSerializer(typeof(ObjectClass));//根据对象类型来创建序列化器
    xs.Serialize (sw, Obj);//进行序列化
    sw.Close ();//关闭文件流

    结果显示为:
     <?xml version="1.0" encoding="UTF-8"?>
    -<ObjectClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <Age>6</Age>
       <Name>ha</Name>
     </ObjectClass>
  • struct对象序列化:
    [Serializable]
    public struct ObjectStruct
    {
    	public ObjectStruct(int age, string name, float salary)
    	{
    		Age = age;
    		Name = name;
    		Salary = salary;
    	}
    	public int Age;
    	public string Name;
    	public float Salary;
    }
    Obj = new ObjectStruct(60, "wow", 600);//obj为该类的公有字段,为其赋值
    StreamWriter sw = new StreamWriter("objStructXml.xml");
    XmlSerializer xs = new XmlSerializer(typeof(ObjectStruct));
    xs.Serialize (sw, Obj);
    sw.Close ();
    结果显示为:
     <?xml version="1.0" encoding="UTF-8"?>
    -<ObjectStruct xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <Age>60</Age>
        <Name>wow</Name>
        <Salary>600</Salary>
     </ObjectStruct>
  • 对象数组序列化:
    ObjArr = new ObjectClass[2];
    ObjArr[0] = new ObjectClass(8, "arr1", 80);
    ObjArr[1] = new ObjectClass(9, "arr2", 90);
    StreamWriter sw = new StreamWriter("objClassArrayXml.xml");
    XmlSerializer xs = new XmlSerializer(typeof(ObjectClass[]));
    xs.Serialize (sw, ObjArr);
    sw.Close ();
    结果显示为:
     <?xml version="1.0" encoding="UTF-8"?>
    -<ArrayOfObjectClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      -<ObjectClass>
          <Age>8</Age>
          <Name>arr1</Name>
        </ObjectClass>
       -<ObjectClass>
          <Age>9</Age>
          <Name>arr2</Name>
        </ObjectClass>
    </ArrayOfObjectClass>
  • 对象List序列化:
    ObjectClass objC = new ObjectClass(4, "ni", 40);
    ListObjC.Add (objC);//ListObjC为public List<ObjectClass> ListObjC = new List<ObjectClass>(2);
    objC = new ObjectClass(5, "hao", 50);
    ListObjC.Add (objC);
    StreamWriter swL = new StreamWriter("objClassListXml.xml");
    XmlSerializer xsL = new XmlSerializer(typeof(List<ObjectClass>));
    xsL.Serialize (swL, ListObjC);
    swL.Close ();
    结果显示为:
     <?xml version="1.0" encoding="UTF-8"?>
    -<ArrayOfObjectClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     -<ObjectClass>
        <Age>4</Age>
        <Name>ni</Name>
      </ObjectClass>
     -<ObjectClass>
        <Age>5</Age>
        <Name>hao</Name>
      </ObjectClass>
    </ArrayOfObjectClass>
  • 字段为类类型的类序列化:
    [Serializable]
    public class ObjectComplexClass
    {
    	public ObjectComplexClass ():this(0, "", 0.0f)
    	{
    	}
    	public ObjectComplexClass(ObjectClass obj)
    	{
    		Obj = obj;
    	}
    	public ObjectComplexClass (int age, string name, float salary)
    	{
    		Obj = new ObjectClass(age, name, salary);
    	}
    	public ObjectClass Obj;//公有字段为类ObjectClass
    }
    ObjComplexC = new ObjectComplexClass(ObjC);//ObjComplexC为public ObjectComplexClass ObjComplexC;
    StreamWriter swC = new StreamWriter("objComplexClassXml.xml");
    XmlSerializer xsC = new XmlSerializer(typeof(ObjectComplexClass));
    xsC.Serialize (swC, ObjComplexC);
    swC.Close ();
    显示结果为:
    <?xml version="1.0" encoding="UTF-8"?>
    -<ObjectComplexClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        -<Obj>
          <Age>6</Age>
          <Name>ha</Name>
         </Obj>
    </ObjectComplexClass>
  • .NET框架不支持关联容器序列化,但是可以通过实现IXmlSerializer接口或利用List<>来实现Dictionary<>的序列化。
反序列化:
  • 步骤:首先构建反序列化器;然后调用Deserialize函数来创建对象的副本(反序列化时必须将返回的对象转型为原始类型)。
  • 各种反序列化代码与上面序列化相对应~仅给出一个
    StreamReader srO = new StreamReader("objClassXml.xml");
    XmlSerializer xsO = new XmlSerializer(typeof(ObjectClass));
    ObjectClass oc = (ObjectClass)xsO.Deserialize (srO);//这里有转型,不要忘记
    srO.Close ();
             可以调用显示函数看到Age为6,Name为ha。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010145745/article/details/33370457

智能推荐

JWT(Json Web Token)实现无状态登录_无状态token登录-程序员宅基地

文章浏览阅读685次。1.1.什么是有状态?有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session。例如登录:用户登录后,我们把登录者的信息保存在服务端session中,并且给用户一个cookie值,记录对应的session。然后下次请求,用户携带cookie值来,我们就能识别到对应session,从而找到用户的信息。缺点是什么?服务端保存大量数据,增加服务端压力 服务端保存用户状态,无法进行水平扩展 客户端请求依赖服务.._无状态token登录

SDUT OJ逆置正整数-程序员宅基地

文章浏览阅读293次。SDUT OnlineJudge#include<iostream>using namespace std;int main(){int a,b,c,d;cin>>a;b=a%10;c=a/10%10;d=a/100%10;int key[3];key[0]=b;key[1]=c;key[2]=d;for(int i = 0;i<3;i++){ if(key[i]!=0) { cout<<key[i.

年终奖盲区_年终奖盲区表-程序员宅基地

文章浏览阅读2.2k次。年终奖采用的平均每月的收入来评定缴税级数的,速算扣除数也按照月份计算出来,但是最终减去的也是一个月的速算扣除数。为什么这么做呢,这样的收的税更多啊,年终也是一个月的收入,凭什么减去12*速算扣除数了?这个霸道(不要脸)的说法,我们只能合理避免的这些跨级的区域了,那具体是那些区域呢?可以参考下面的表格:年终奖一列标红的一对便是盲区的上下线,发放年终奖的数额一定一定要避免这个区域,不然公司多花了钱..._年终奖盲区表

matlab 提取struct结构体中某个字段所有变量的值_matlab读取struct类型数据中的值-程序员宅基地

文章浏览阅读7.5k次,点赞5次,收藏19次。matlab结构体struct字段变量值提取_matlab读取struct类型数据中的值

Android fragment的用法_android reader fragment-程序员宅基地

文章浏览阅读4.8k次。1,什么情况下使用fragment通常用来作为一个activity的用户界面的一部分例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章 – 2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输_android reader fragment

FFT of waveIn audio signals-程序员宅基地

文章浏览阅读2.8k次。FFT of waveIn audio signalsBy Aqiruse An article on using the Fast Fourier Transform on audio signals. IntroductionThe Fast Fourier Transform (FFT) allows users to view the spectrum content of _fft of wavein audio signals

随便推点

Awesome Mac:收集的非常全面好用的Mac应用程序、软件以及工具_awesomemac-程序员宅基地

文章浏览阅读5.9k次。https://jaywcjlove.github.io/awesome-mac/ 这个仓库主要是收集非常好用的Mac应用程序、软件以及工具,主要面向开发者和设计师。有这个想法是因为我最近发了一篇较为火爆的涨粉儿微信公众号文章《工具武装的前端开发工程师》,于是建了这么一个仓库,持续更新作为补充,搜集更多好用的软件工具。请Star、Pull Request或者使劲搓它 issu_awesomemac

java前端技术---jquery基础详解_简介java中jquery技术-程序员宅基地

文章浏览阅读616次。一.jquery简介 jQuery是一个快速的,简洁的javaScript库,使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJAX交互 jQuery 的功能概括1、html 的元素选取2、html的元素操作3、html dom遍历和修改4、js特效和动画效果5、css操作6、html事件操作7、ajax_简介java中jquery技术

Ant Design Table换滚动条的样式_ant design ::-webkit-scrollbar-corner-程序员宅基地

文章浏览阅读1.6w次,点赞5次,收藏19次。我修改的是表格的固定列滚动而产生的滚动条引用Table的组件的css文件中加入下面的样式:.ant-table-body{ &amp;amp;::-webkit-scrollbar { height: 5px; } &amp;amp;::-webkit-scrollbar-thumb { border-radius: 5px; -webkit-box..._ant design ::-webkit-scrollbar-corner

javaWeb毕设分享 健身俱乐部会员管理系统【源码+论文】-程序员宅基地

文章浏览阅读269次。基于JSP的健身俱乐部会员管理系统项目分享:见文末!

论文开题报告怎么写?_开题报告研究难点-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏15次。同学们,是不是又到了一年一度写开题报告的时候呀?是不是还在为不知道论文的开题报告怎么写而苦恼?Take it easy!我带着倾尽我所有开题报告写作经验总结出来的最强保姆级开题报告解说来啦,一定让你脱胎换骨,顺利拿下开题报告这个高塔,你确定还不赶快点赞收藏学起来吗?_开题报告研究难点

原生JS 与 VUE获取父级、子级、兄弟节点的方法 及一些DOM对象的获取_获取子节点的路径 vue-程序员宅基地

文章浏览阅读6k次,点赞4次,收藏17次。原生先获取对象var a = document.getElementById("dom");vue先添加ref <div class="" ref="divBox">获取对象let a = this.$refs.divBox获取父、子、兄弟节点方法var b = a.childNodes; 获取a的全部子节点 var c = a.parentNode; 获取a的父节点var d = a.nextSbiling; 获取a的下一个兄弟节点 var e = a.previ_获取子节点的路径 vue