序列化和反序列化的几种方式(JavaScriptSerializer 、XmlSerializer、DataContractSerializer)(一)

JavaScriptSerializer 类

为启用 AJAX 的应用程序提供序列化和反序列化功能。

命名空间: System.Web.Script.Serialization

程序集: System.Web.Extensions(在 System.Web.Extensions.dll 中)

      JavaScriptSerializer 类由异步通信层内部使用,用于序列化和反序列化在浏览器和 Web 服务器之间传递的数据。 您无法访问序列化程序的此实例。 但是,此类公开了公共 API。 因此,当您希望在托管代码中使用 JavaScript 对象符号 (JSON) 时可以使用此类。

若要序列化对象,请使用 Serialize 方法。 若要反序列化 JSON 字符串,请使用 Deserialize DeserializeObject 方法。 若要序列化和反序列化 JavaScriptSerializer 本身不支持的类型,请使用 JavaScriptConverter 类来实现自定义转换器。 然后,使用 RegisterConverters 方法注册转换器。

关于SerializeDeserialize的应用:

 

 
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Web.Script.Serialization;
 7 namespace Wolfy.SerializerDemo
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             List<Person> persons = new List<Person>{
14                                    new Person("wolfy",24,Convert.ToDateTime("1989-04-11")),
15                                    new Person("张三",23,Convert.ToDateTime("1990-04-11")),
16                                    new Person("李四",22,Convert.ToDateTime("1991-04-11")),
17                                    new Person("王五",21,Convert.ToDateTime("1992-04-11"))
18                                };
19             //创建JavaScriptSerializer对象
20             JavaScriptSerializer jss = new JavaScriptSerializer();
21             //调用序列化方法Serialize
22             string json = jss.Serialize(persons);
23             Console.WriteLine("序列化.....");
24             Console.WriteLine(json);
25             Console.WriteLine("反序列化.....");
26             JavaScriptSerializer jss2 = new JavaScriptSerializer();
27             List<Person> list = jss2.Deserialize<List<Person>>(json);
28             foreach (Person item in list)
29             {
30                 Console.WriteLine(item.Name + "\t" + item.Age.ToString() + "\t" + item.Birthday);
31             }
32        
33             Console.Read();
34         }
35     }
36 }
 

Person类

 
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace Wolfy.SerializerDemo
 8 {
 9     public class Person
10     {
11         public Person() { }
12         public Person(string name, int age, DateTime bithday)
13         {
14             this.name = name;
15             this.age = age;
16             this.birthday = bithday;
17         }
18         private string name;
19 
20         public string Name
21         {
22             get { return name; }
23             set { name = value; }
24         }
25         private int age;
26 
27         public int Age
28         {
29             get { return age; }
30             set { age = value; }
31         }
32         private DateTime birthday;
33 
34         public DateTime Birthday
35         {
36             get { return birthday; }
37             set { birthday = value; }
38         }
39     }
40 }

运行结果:

注意:Date 对象,在 JSON 中表示为“\/Date(刻度数)\/”。 刻度数是一个正的或负的长值,该值指示从 UTC 1970 年 1 月 1 日午夜开始已经过的刻度数(毫秒)。

所支持的最大日期值为 MaxValue(9999 年 12 月 31 日 11:59:59 PM),而所支持的最小日期值为 MinValue(0001 年 1 月 1 日 12:00:00 AM)。如果想得到如“2013-01-01”需要对时间进行转换:这里提供一种js转换的方式,具体方法如下:

简单的分页存储过程,Json格式日期转换为一般日期

在对Person序列化需注意:Person类要有无参的构造函数。不然在反序列化时会出现如下错误:

XmlSerializer类

将对象序列化到 XML 文档中和从 XML 文档中反序列化对象。XmlSerializer 使您得以控制如何将对象编码到 XML 中。

命名空间:System.Xml.Serialization
程序集:System.Xml(在 system.xml.dll 中)

XML 序列化是将对象的公共属性 (Property) 和字段转换为序列格式(这里是指 XML)以便存储或传输的过程。反序列化则是从 XML 输出中重新创建原始状态的对象。因此,可以将序列化视为将对象的状态保存到流或缓冲区的方法。例如,ASP.NET 使用 XmlSerializer 类对 XML Web services 消息进行编码。

对象中的数据是用编程语言构造来描述的,如类、字段、属性 (Property)、基元类型、数组,甚至 XmlElement XmlAttribute 对象形式的嵌入 XML。您可以创建自己的用属性 (Attribute) 批注的类,或使用 XML 架构定义工具 (Xsd.exe) 生成基于现有 XML 架构定义 (XSD) 文档的类。如果有 XML 架构,则可以运行 XSD.exe 产生一组类,将这组类的类型强声明为此架构,并用属性 (Attribute) 批注这些类以便在序列化时遵循此架构。

在对象和 XML 之间传输数据需要从编程语言构造到 XML 架构的映射和从 XML 架构到编程语言构造的映射。XmlSerializer 和相关工具(如 Xsd.exe)在设计时和运行时都能在这两种技术之间提供一个桥梁。在设计时,使用 Xsd.exe 可从自定义类产生 XML 架构文档 (.xsd) 或从给定架构产生类。不论何种情况,这些类都用自定义属性 (Attribute) 批注,以指示 XmlSerializer 如何在 XML 架构系统和公共语言运行库之间映射。在运行时,可以将这些类的实例序列化到遵循给定架构的 XML 文档中。同样,可以将这些 XML 文档反序列化到运行时对象中。注意,XML 架构是可选的,在设计时或运行时不是必需的。

控制生成的 XML

为控制所生成的 XML,可以向类和成员应用特殊属性 (Attribute)。例如,为指定不同的 XML 元素名称,可以将 XmlElementAttribute 应用于公共字段或属性 (Property),同时设置 ElementName 属性 (Property)。有关类似属性的完整列表,请参见 控制 XML 序列化的属性。也可以实现 IXmlSerializable 接口以控制 XML 输出。

如果所生成的 XML 必须符合万维网联合会 (www.w3.org) 文档“简单对象访问协议 (SOAP) 1.1”的第 5 部分,则必须利用 XmlTypeMapping 构造 XmlSerializer。若要进一步控制编码后的 SOAP XML,请使用 控制编码的 SOAP 序列化的属性 中所列的属性 (Attribute)。

有了 XmlSerializer,可以利用使用强类型类的优点并仍具有 XML 的灵活性。通过在强类型类中使用类型为 XmlElementXmlAttribute XmlNode 的字段或属性 (Property),可以将部分 XML 文档直接读入 XML 对象中。

如果使用扩展 XML 架构,则也可以使用 XmlAnyElementAttribute XmlAnyAttributeAttribute 属性 (Attribute) 来序列化及反序列化在原始架构中找不到的元素或属性 (Attribute)。若要使用这些对象,请将 XmlAnyElementAttribute 应用到返回 XmlElement 对象数组的字段中,或者将 XmlAnyAttributeAttribute 应用到返回 XmlAttribute 对象数组的字段中。

如果属性 (Property) 或字段返回一个复杂对象(如数组或类实例),则 XmlSerializer 将其转换为嵌套在主 XML 文档内的元素。例如,以下代码中的第一个类返回第二个类的实例。

XmlSerializer默认的序列化规则

       对于一般的数据对象(这里就用上面的Person类来说明),使用XmlSerializer对其进行序列化后会生成怎样的XML结构。首先定义一个辅助方法专门进行基于XmlSerializer的序列化操作。

 
1  static void Serialize<T>(T instance, string fileName)
2         {
3             using (XmlWriter writer = new XmlTextWriter(fileName, Encoding.UTF8))
4             {
5                 XmlSerializer serializer = new XmlSerializer(typeof(T));
6                 serializer.Serialize(writer, instance);
7             }
8         }
 

在控制台程序中,通过调用上面的Serialize<T>方法将创建的Person对象序列化保存在xml文件中。

1     static void Main(string[] args)
2         {
3             Person p = new Person("Wolfy", 24, Convert.ToDateTime("1989-04-11"));
4             Serialize<Person>(p, "person.xml");
5             Console.Read();
6         }

上面程序执行后,打开生成的person.xml文件,如下所示xml代表序列化后生成的xml结构。

<?xml version="1.0" encoding="utf-8"?><Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Name>Wolfy</Name><Age>24</Age><Birthday>1989-04-11T00:00:00</Birthday></Person>

      从而得出XmlSerializer在默认的情况下的序列化规则:

  • XML根节点的名称为对象类型的名称,并且没有命名空间。
  • 对象属性或字段成员以XmlElement的形式输出,名称和属性/字段名称一致,并且不具有命名空间。
  • 只有public属性/字段成员才会参与序列化(private的字段并不会序列化)。
  • XmlEmlement的顺序与对应的属性或字段在类型中定义的顺序一致。

注意:这里同样得定义一个空的无参构造函数。这个函数是必须的,因为反序列化的时候需要调用它创建对象。如果将其从成员列表中移除,在序列化的时候会抛出InvalidOptionException异常,并提示"Person无法序列化因为它没有无参的构造函数"。

对于被序列化对象的属性,不仅要求是共有的,还要求是可读写的,如果将Person类中age和birthday分别改成只读/写的属性。如下:

 
 1  public int Age
 2         {
 3             get { return age; }
 4             //set { age = value; }
 5         }
 6         private DateTime birthday;
 7 
 8         public DateTime Birthday
 9         {
10             //get { return birthday; }
11             set { birthday = value; }
12         }
 

执行控制台程序,执行结果如下,可见只读、写的age和birthday并没有出现在序列化的xml中。

<?xml version="1.0" encoding="utf-8"?><Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Name>Wolfy</Name></Person>

如果是自定义自动实现的属性,定义成下面的这两种方式,Person对象是不能被序列化的

通过定制XmlSerializer控制XML结构

          上面列出的仅仅是XmlSerializer采用的默认序列化规则。在很多情况下,我们需要序列化生成的XML符合一个既定的XSD,那么就需要对xmlSerializer的序列化进行人工的干预和控制。

          对最终生成的XML结构的控制可以通过在数据类型和它的字段/属性成员上应用相应的特性来实现。

  • 在类型上应用XmlRootAttribute特性,通过Name和Namespace属性改变根节点的名称和命名空间。
  • 在字段/属性上应用System.Xml.Serialization.XmlAttributeAttribute特性将其序列化成XML属性,同时通过AttributeName和Namespace属性指定XML属性的名称和命名空间。
  • 在字段/属性上应用System.Xml.Serialization.XmlAttributeAttribute特性将其序列化成XML元素,同时通过AttributeName、Namespace和Order属性指定XML属性的名称和命名空间和先后次序。

我们可以按照如下的方式在类型上应用XmlRootAttribute特性对ElementName和Namespace属性进行相应的设置最终控制根节点的元素名称和命名空间。在属性Name上应用XmlAttributeAttrubute特性让该属性以XML属性的形式被序列化。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
namespace Wolfy.XmlSerializerDemo
{
    [XmlRoot(ElementName = "Per", Namespace = "http://www.artech.com")]
    public class Person
    {
        public Person() { }
        public Person(string name, int age, DateTime bithday)
        {
            this.name = name;
            this.age = age;
            this.birthday = bithday;
        }
        private string name;
        [XmlAttribute]
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private int age;

        public int Age
        {
            get { return age; }
            set { age = value; }
        }
        private DateTime birthday;

        public DateTime Birthday
        {
            get { return birthday; }
            set { birthday = value; }
        }
    }
}

Person

 

生成的xml文件:

<?xml version="1.0" encoding="utf-8"?><Per xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="Wolfy" xmlns="http://www.artech.com"><Age>24</Age><Birthday>1989-04-11T00:00:00</Birthday></Per>

反序列化通用方法:

 
1  static T Desirialize<T>(string fileName)
2         {
3             using (FileStream fs = new FileStream(fileName, FileMode.Open))
4             {
5                 XmlSerializer serializer = new XmlSerializer(typeof(T));
6                 return (T)serializer.Deserialize(fs);
7             }
8 
9         }
 

参考文献:

           MSDN:

                    http://msdn.microsoft.com/zh-cn/library/system.xml.serialization.xmlserializer(VS.80).aspx

                    http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx

           《WCF全面解析 上册》蒋金楠 著 电子工业出版社

 

关于序列化先总结到这里,关于DataContractSerializer之后会用专门一篇来总结。

自己不是大牛,但是也说的上一个进击的小菜......

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。