序列化和反序列化的幾種方式(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屬性的形式被序列化。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Xml;
 7 using System.Xml.Serialization;
 8 namespace Wolfy.XmlSerializerDemo
 9 {
10     [XmlRoot(ElementName = "Per", Namespace = "http://www.artech.com")]
11     public class Person
12     {
13         public Person() { }
14         public Person(string name, int age, DateTime bithday)
15         {
16             this.name = name;
17             this.age = age;
18             this.birthday = bithday;
19         }
20         private string name;
21         [XmlAttribute]
22         public string Name
23         {
24             get { return name; }
25             set { name = value; }
26         }
27         private int age;
28 
29         public int Age
30         {
31             get { return age; }
32             set { age = value; }
33         }
34         private DateTime birthday;
35 
36         public DateTime Birthday
37         {
38             get { return birthday; }
39             set { birthday = value; }
40         }
41     }
42 }
Person


生成的xml文件:

1 <?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>
person.xml

反序列化通用方法:

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之后會用專門一篇來總結。

自己不是大牛,但是也說的上一個進擊的小菜......

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM