什麼是序列化
?
可能許多開發人員曾沒聽過或沒使用過,
序列化是將物件狀態轉換為可保存或可傳輸格式的處理序。而
什麼是反序列化
?
也就是
序列化的反面,就是在還原序列化,它可以將資料流轉換成物件。說到這裡可能還是有些人不太懂也覺得很抽象,簡單來說,
序列化的目的就是讓資料易於儲存和傳輸,是將一個物件的公用屬性和欄位轉換成
XML
格式或其他資料流傳輸格式,反序列化則是還原為物件,以易於程式取得物件資料與處理。
若還不清楚,可直接看以下
示範
例子:
如何序列化XML
示範如何利用類別公用欄位和屬性將資料儲存為*.xml檔案:
1.定義欲序列化物件的公用欄位和屬性。
2.使用XmlSerializer並呼叫 Serialize 方法來產生 XML檔案。
序列化程式碼
using System.Xml;
using System.Xml.Serialization;
using System.IO;
public static class XmlSerialize
/// <summary>
/// 將類別序列化並產生XML檔案
/// </summary>
/// <param name="fileName">建立XML檔案目標路徑</param>
/// <param name="obj"></param>
public static void SerializeToXml(string fileName, object obj)
Stream stream = null;
StreamWriter writer = null;
XmlSerializer xml = new XmlSerializer(obj.GetType());
stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read);
writer = new StreamWriter(stream, Encoding.UTF8);
xml.Serialize(writer, obj);
catch (Exception ex)
throw ex;
finally
writer.Close();
stream.Close();
示範用法
Person p = new Person();
p.Name = "M.K.";
p.Phone = "0950123456";
XmlSerialize.SerializeToXml(AppDomain.CurrentDomain.BaseDirectory + "person.xml", p);
XML序列化結果
如何泛型反序列化XML
反序列化的物件型別可能有很多種,這裡直接利用泛型方法回傳該物件的型別,以下為示範如何利用反序列化取得*.xml檔案內容:
反序列化程式碼
/// <summary>
/// 反序列化XML檔案內容
/// </summary>
/// <param name="FileName">XML檔案路徑</param>
public static T DeserializeFromXml<T>(string FileName)
Stream stream = null;
StreamReader reader = null;
XmlSerializer xml = new XmlSerializer(typeof(T));
stream = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.None);
reader = new StreamReader(stream, Encoding.UTF8);
object obj = xml.Deserialize(reader);
return (T)obj;
catch (Exception ex)
return default(T);
finally
stream.Close();
reader.Close();
在這裡的default(T)表示為該物件的預設值,default預設關鍵字的說明可查看MSDN – 泛型程式碼中的預設關鍵字 (C# 程式設計手冊) ,在反序列化時並不是所有的物件都能反序列化,當反序列化失敗,則回傳該物件的預設值。
Person person = XmlSerialize.DeserializeFromXml<Person>(AppDomain.CurrentDomain.BaseDirectory + "person.xml");
string result = string.Format("名字:{0},手機:{1}", person.Name, person.Phone);
// 執行結果result = 名字:M.K.,手機:0950123456
如何定義欲序列化的類別
介紹到這裡對於基本的序列化和反序列化功能也有所了解了,上述示範的物件類別只要公開欄位和屬性,沒有特別自訂控制序列化的欄位和屬性,序列化過程中系統會預設忽略private和protected成員,將每個公開成員都自動被序列化成xml element。可是有時候公開的資料必不想要被序列化,又該如何處理? 示範自訂序列化類別的程式碼如下:
預期執行結果的Xml內容
定義欲序列化類別
[Serializable, XmlRoot("ContactList")]
public class ContactList
List<Person> pvContactList;
[XmlElement("Person")]
public List<Person> ContactLists { get { return pvContactList; } set { pvContactList = value; } }
[XmlRoot("Person")]
public class Person
string firstName = string.Empty;
string lastName = string.Empty;
public Person()
pvAddrList = new List<Address>();
public Person(string firstName, string lastName)
this.firstName = firstName;
this.lastName = lastName;
pvAddrList = new List<Address>();
[XmlAttribute("FirstName")]
public string FirstName
get { return firstName; }
pvName = value + " " + LastName;
firstName = value;
[XmlAttribute("LastName")]
public string LastName
get { return lastName; }
pvName = FirstName + " " + value;
lastName = value;
string pvName = string.Empty;
[XmlIgnore]
public string Name
if (string.IsNullOrEmpty(pvName))
pvName = FirstName + " " + LastName;
return pvName;
string phone = string.Empty;
[XmlAttribute("Phone")]
public string Phone { get { return phone; } set { phone = value; } }
List<Address> pvAddrList;
[XmlElement("Address")]
public List<Address> AddrList { get { return pvAddrList; } set { pvAddrList = value; } }
[XmlRoot("Address")]
public class Address
[XmlElement]
public string City { get; set; }
[XmlElement("ZipCode")]
public int ZipCode { get; set; }
[XmlElement("BillsAddress")]
public string BillsAddress { get; set; }
Person p = new Person("Steve","Jobs");
p.Phone = "0950123456";
List<Address> addrlist = new List<Address>();
addrlist.Add(new Address { City = "Taipei", ZipCode = 11575, BillsAddress = "台北市南港區忠孝東路六段21號10樓之2" });
addrlist.Add(new Address { City = "Taipei", ZipCode = 11575, BillsAddress = "台北市南港區忠孝東路五段815號8樓" });
p.AddrList = addrlist;
ContactList list = new ContactList();
list.ContactLists = new List<Person> { p };
XmlSerialize.SerializeToXml(AppDomain.CurrentDomain.BaseDirectory + "person.xml", list);
序列化處理類別時,加入「Serializable」屬性就可被序列化,公開成員可省略不寫Serializable即可被序列化。
使用「XmlIgnore」屬性可不被序列化,可觀察到Person類別中有個公開名為Name的屬性,但是該屬性有加上「XmlIgnore」,執行序列化Xml後的內容沒有該資料。
序列化類別必須要有建構式,否則無法進行序列化,顯示錯誤訊息為沒有參數建構函式。
若於Person類別增加Birthday屬性程式碼如下:
Person類別增加Birthday屬性
[XmlAttribute("Birthday")]
public DateTime? Birthday { get; set; }
竟發生下圖的執行錯誤訊息,原因是Xml序列化過程中DateTime不可為空字串或含空白值,需經過處理才可正常運作。
調整DateTime屬性寫法,與給p.Birthday值:
序列化DateTime正確屬性寫法
[XmlIgnore]
public DateTime? Birthday { get; set; }
[XmlAttribute("Birthday")]
public string StrBirthday
get { return Birthday.HasValue ? Birthday.Value.ToString("yyyy/MM/dd") : null; }
set { Birthday = DateTime.Parse(value); }
執行結果 – Birthday可正常顯示
Xml序列化應用的地方很多也很好用,使用過後會發現是儲存和物件處理的不錯選擇,希望大家都能透過本篇更進一步多了解序列化和反序列化的使用。
MSDN參考資料
XML 和 SOAP 序列化
控制 XML 序列化的屬性
[C#.NET] 利用 泛型方法 重構 反序列化
Force XmlSerializer to serialize DateTime as ‘YYYY-MM-DD hh:mm:ss’
字符串”2013/5/18 0:00:00”不是有效的 AllXsd 值
詮力科技為一專業的軟體開發服務公司,十多年來以前瞻的商業眼光搭配完善的專業技術與全力的服務使命,致力於提供金融產業、政府公部門以及中小企業完善的「商業簡訊服務」,並推出「MMS多媒體簡訊」、「雲端儲存設備ITE2 NAS」、「行動網頁空間服務」、「信用卡安全防偽系統」、「Share
Point解決方案」、「SSO單一登入系統建置」等多種服務項目。詮力更深信客戶的需求和服務應永遠優先於產品的制式規劃與銷售,為客戶提供客製化的產品規劃,先進科技的價值才能充份地被瞭解。
了解更多關於詮力
About iTe2
We are ITE2 Technology Inc., and we have a new vision for software development services. We lead clients through accelerating change, helping them with the power of technology to deliver new outcomes from their business. We have established lots of partner relationships, including banking industries, government, many of leading enterprises and brands. In ITE2, we proudly provide services including business SMS solutions, MMS, Network attached storage – ITE2 NAS, mobile website services, credit card risk control, share point, SSO single sign-on and many other software services cannot be listed. We believed that customer’ needs should above than anything else. So ITE2 also delivered bunch of great customize software services for customers, as we understood customize can genuinely reflect the technology and our values.