深入理解:XML與對象的序列化與反序列化
更新時間:2013年06月08日 17:41:23 作者:
本篇文章是對XML與對象的序列化與反序列化進行了詳細的分析介紹,需要的朋友參考下
這篇文章主要講述XML與對象的序列化與反序列化。并且會附上一些簡單的序列化與反序列化方法,供大家使用。
假設(shè)我們在一個Web項目中有這樣兩個類
復制代碼 代碼如下:
public class Member
{
public string Num { get; set; }
public string Name { get; set; }
}
public class Team
{
public string Name;
public List<Member> Members { get; set; }
}
假設(shè)我們需要把Team類的一個實例POST到一個URL,
當然,使用Form隱藏域提交就可以完成該功能。
如果該Team包括30條數(shù)據(jù)呢?
為了區(qū)分每個Member,我們得給參數(shù)的名字加上后綴。這就要一大串的隱藏域來完成:
復制代碼 代碼如下:
<!--使用Razor來演示-->
@model Team
<form id="submitForm" action="http://www.johnconnor.com/team" method="post">
<input type="hidden" name="TeamName" value="@Model.Name" />
<input type="hidden" name="MemberNum1" value="@Model.Members[0].Num" />
<input type="hidden" name="MemberName1" value="@Model.Members[0].Name" />
...
<!--省略28X2個input標簽-->
<input type="hidden" name="MemberNum30" value="@Model.Members[29].Num" />
<input type="hidden" name="MemberName30" value="@Model.Members[29].Name" />
</form>
<script type="text/javascript">
document.getElementById("submitForm").submit();
</script>
還敢想象一下如果Team再復雜一些,嵌套再多一些的情況么?
呃,即使你愿意這么傳數(shù)據(jù),對方看到一坨參數(shù)名就夠頭疼了。
我們都知道對象是不能在網(wǎng)絡中直接傳輸?shù)模贿^還有補救的辦法。
XML(Extensible Markup Language)可擴展標記語言,本身就被設(shè)計用來存儲數(shù)據(jù),任何一個對象都可以用XML來描述。以Team類為例:
復制代碼 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<Team xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Development</Name>
<Members>
<Member>
<Num>001</Num>
<Name>Marry</Name>
</Member>
<Member>
<Num>002</Num>
<Name>John</Name>
</Member>
</Members>
</Team>
這樣一個XML文檔就表示了Team一個實例。
聰明的看官應該已經(jīng)想到,XML是可以作為對象信息的載體在網(wǎng)絡中傳輸,因為它是文本形式的。
怎么進行XML文檔與對象的相互轉(zhuǎn)換呢?
XmlSerializer類就是干這個活的。
命名空間:System.Xml.Serialization
程序集:System.Xml(在 system.xml.dll 中)
現(xiàn)在這里展示了一個提供序列化與反序列化方法的EncodeHelper類。
Deserialize方法將XML字符串轉(zhuǎn)換為指定類型的對象;
Serialize方法則將對象轉(zhuǎn)換為XML字符串。
復制代碼 代碼如下:
/// <summary>
/// 提供xml文檔序列化 反序列化
/// </summary>
public sealed class EncodeHelper
{
/// <summary>
/// 反序列化XML字符串為指定類型
/// </summary>
public static object Deserialize(string Xml, Type ThisType)
{
XmlSerializer xmlSerializer = new XmlSerializer(ThisType);
object result;
try
{
using (StringReader stringReader = new StringReader(Xml))
{
result = xmlSerializer.Deserialize(stringReader);
}
}
catch (Exception innerException)
{
bool flag = false;
if (Xml != null)
{
if (Xml.StartsWith(Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble())))
{
flag = true;
}
}
throw new ApplicationException(string.Format("Couldn't parse XML: '{0}'; Contains BOM: {1}; Type: {2}.",
Xml, flag, ThisType.FullName), innerException);
}
return result;
}
/// <summary>
/// 序列化object對象為XML字符串
/// </summary>
public static string Serialize(object ObjectToSerialize)
{
string result = null ;
try
{
XmlSerializer xmlSerializer = new XmlSerializer(ObjectToSerialize.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, new UTF8Encoding(false));
xmlTextWriter.Formatting = Formatting.Indented;
xmlSerializer.Serialize(xmlTextWriter, ObjectToSerialize);
xmlTextWriter.Flush();
xmlTextWriter.Close();
UTF8Encoding uTF8Encoding = new UTF8Encoding(false, true);
result= uTF8Encoding.GetString(memoryStream.ToArray());
}
}
catch (Exception innerException)
{
throw new ApplicationException("Couldn't Serialize Object:" + ObjectToSerialize.GetType().Name, innerException);
}
return result;
}
}
要使用這個類需要添加以下引用
using System;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
下面我們用一個控制臺程序來演示一下這個類是如何工作的。這里是程序的Main函數(shù)。
復制代碼 代碼如下:
static void Main(string[] args)
{
List<Member> Members = new List<Member>();
Member member1 = new Member { Name = "Marry", Num = "001" };
Member member2 = new Member { Name = "John", Num = "002" };
Members.Add(member1);
Members.Add(member2);
Team team = new Team { Name = "Development", Members = Members };
var xml =EncodeHelper.Serialize(team);//序列化
Console.Write(xml);//打印序列化后的XML字符串
Console.ReadLine();
Team newTeam = EncodeHelper.Deserialize(xml, typeof(Team)) as Team;//反序列化時需要顯式的進行類型轉(zhuǎn)換
Console.WriteLine("Team Name:"+newTeam.Name);//顯示反序列化后的newTeam對象
foreach (var member in newTeam.Members)
{
Console.WriteLine("Member Num:" + member.Num);
Console.WriteLine("Member Name:" + member.Name);
}
Console.ReadLine();
}
在執(zhí)行完Console.Write(xml)這行代碼后,就可以看到打印出來的XML文檔了。
復制代碼 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<Team xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Development</Name>
<Members>
<Member>
<Num>001</Num>
<Name>Marry</Name>
</Member>
<Member>
<Num>002</Num>
<Name>John</Name>
</Member>
</Members>
</Team>
與我在文章開頭給出的例子是一模一樣的。
最終反序列化出來的newTeam對象打印出來是這樣的結(jié)果。
Team Name:Development
Member Num:001
Member Name:Marry
Member Num:002
Member Name:John
回到我們開頭的Web通信的例子,
利用XML序列化與反序列化來進行對象傳遞,我們只需要把需要傳遞的對象序列化為XML字符串,使用一個隱藏域進行form提交就可以搞定咯!
接收方再將接收到的XML字符串反序列化成預設(shè)的對象即可。前提是雙方必須約定序列化與反序列化的過程一致,且對象相同。
最后我們來看一下怎么利用一些特性來控制序列化與反序列化操作的過程。我們把開始的類改一下:
復制代碼 代碼如下:
public class Member
{
[XmlElement("Member_Num")]
public string Num { get; set; }
public string Name { get; set; }
}
[XmlRoot("Our_Team")]
public class Team
{
[XmlIgnore]public string Name;
public List<Member> Members { get; set; }
}
然后我們再次執(zhí)行剛才的控制臺程序,序列化結(jié)果變成了這樣:
復制代碼 代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<Our_Team xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Members>
<Member>
<Member_Num>001</Member_Num>
<Name>Marry</Name>
</Member>
<Member>
<Member_Num>002</Member_Num>
<Name>John</Name>
</Member>
</Members>
</Our_Team>
本來的根節(jié)點Team變成了Our_Team,Member的子節(jié)點Num變成了Member_Num,并且Team的Name子節(jié)點被忽略了。
可見特性XmlRoot可以控制根節(jié)點的顯示和操作過程,XmlElement則針對子節(jié)點。如果某些成員被標記XmlIgnore,則在序列化與反序列化過程中會被忽略。
這些特性的具體內(nèi)容可以在MSDN查看,就不多講了。
有了這些知識,在網(wǎng)絡中傳遞對象數(shù)據(jù)應該已經(jīng)難不倒各位看官了把。^_^
相關(guān)文章
使用php語句將數(shù)據(jù)庫*.sql文件導入數(shù)據(jù)庫
這篇文章主要介紹了如何使用php語句將數(shù)據(jù)庫*.sql文件導入數(shù)據(jù)庫,需要的朋友可以參考下2014-05-05PHP中new static() 和 new self() 的區(qū)別介紹
這篇文章主要介紹了PHP中new static() 和 new self() 的區(qū)別介紹,需要的朋友可以參考下2015-01-01微信自定義菜單的創(chuàng)建/查詢/取消php示例代碼
這篇文章主要為大家詳細介紹了微信自定義菜單的創(chuàng)建/查詢/取消php示例代碼,感興趣的小伙伴們可以參考一下2016-08-08php實現(xiàn)的仿阿里巴巴實現(xiàn)同類產(chǎn)品翻頁
當前頁左邊的頁碼為最新的產(chǎn)品,按更新時間呈升序排列;右邊的頁碼為早期的產(chǎn)品, 按更新時間呈降序排列。2009-12-12詳談php中 strtr 和 str_replace 的效率問題
下面小編就為大家?guī)硪黄斦刾hp中 strtr 和 str_replace 的效率問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05