1. 程式人生 > >Unity序列化之XML,JSON--------合成與解析【轉載】

Unity序列化之XML,JSON--------合成與解析【轉載】

尊重原創,轉載請註明出處,謝謝!

最近在學熱更新,涉及到資源熱更,所以就瞭解了XML,JSON相關的東西。這方面網上資料還是比較多的,所以這裡主要是總結一下基本使用方法和一些應用的Demo。

1.先介紹一下 XML 和 JSON 是什麼東西吧?

(1)XML

擴充套件標記語言 (Extensible Markup Language, XML) ,用於標記電子檔案使其具有結構性的標記語言,可以用來標記資料、定義資料型別,是一種允許使用者對自己的標記語言進 行定義的源語言。 XML使用DTD(document type definition)文件型別定義來組織資料;格式統一,跨平臺和語言,早已成為業界公認的標準。 XML是標準通用標記語言 (SGML) 的子集,非常適合 Web 傳輸。XML 提供統一的方法來描述和交換獨立於應用程式或供應商的結構化資料。

(2)Json

JSON(JavaScript Object Notation)一種輕量級的資料交換格式,具有良好的可讀和便於快速編寫的特性。可在不同平臺之間進行資料交換。JSON採用相容性很高的、完全獨立於語言文字格式,同時也具備類似於C語言的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)體系的行為。這些特性使JSON成為理想的資料交換語言。

說了那麼多,其實就是資料的兩種儲存格式。主要用於配置檔案,描述資料,儲存資料,資料傳輸等等。

2.因為Xml和Json都可以辦到這些事情,那麼它們之間有什麼區別麼?各自的優缺點?

(1)XML

優點:格式統一,符合標準;.容易與其他系統進行遠端互動,資料共享比較方便。

        缺點:XML檔案龐大,檔案格式複雜,傳輸佔頻寬;伺服器端和客戶端解析XML花費較多的資源和時間;需要花費大量程式碼來解析XML;

(2)Json

優點:資料格式比較簡單,易於讀寫,格式都是壓縮的,佔用頻寬小;.支援多種語言;

        缺點:可讀性較xml略差;

         總而言之,兩者可以相互轉換,功能都是相差無幾的。但是json比xml較好,但xml更加通用。

3.XML使用的簡單介紹.

a.先來看一段簡單的xml程式碼。

  1. <team name="Dreamer">
  2. <student>
  3. <name>Tom</name
    >
  4. <age>20</age>
  5. <id>20111234</id>
  6. </student>
  7. <student>
  8. <name>Shierly</name>
  9. <age>19</age>
  10. <id>20113210</id>
  11. </student>
  12. <student>
  13. <name>Lili</name>
  14. <age>21</age>
  15. <id>20111110</id>
  16. </student>
  17. </team>
很顯然,可以看出來,這段程式碼描述的是一個名叫Dreamer的團隊有三個成員,還分別記錄了這三個成員的相關資訊。所以可以看出來XML的可讀性十分強。所以我們可以用XML去描述 我們程式碼中的一些資料關係,描述一個物件。這也就是將物件序列化。然後使用的地方再將xml檔案解析出來重新組成原來的物件,這就實現了複雜資料的傳輸。 b.在untiy中用程式碼生成xml檔案。( 可以使用C#自帶的庫,不需要引入其他庫。using System.Xml )
  1. public void CreateXML()
  2. {
  3. //xml儲存的路徑,注意路徑。
  4. string filepath = "E:/my.xml";
  5. //繼續判斷當前路徑下是否有該檔案
  6. if(!File.Exists (filepath))
  7. {
  8. //建立XML文件例項
  9. XmlDocument xmlDoc = new XmlDocument();
  10. //建立root節點,也就是最上一層節點
  11. XmlElement root = xmlDoc.CreateElement("team");
  12. root.SetAttribute("name", "Dreamer");
  13. //繼續建立下一層節點
  14. XmlElement student = xmlDoc.CreateElement("student");
  15. //繼續建立下一層節點
  16. XmlElement name = xmlDoc.CreateElement("name");
  17. //設定節點中的數值
  18. name.InnerText = "Tom";
  19. XmlElement age = xmlDoc.CreateElement("age");
  20. age.InnerText = "20";
  21. XmlElement id = xmlDoc.CreateElement("id");
  22. id.InnerText = "20111234";
  23. //把節點一層一層的新增至XMLDoc中 ,請仔細看它們之間的先後順序,這將是生成XML檔案的順序
  24. student.AppendChild(name);
  25. student.AppendChild(age);
  26. student.AppendChild(id);
  27. root.AppendChild(student);
  28. student = xmlDoc.CreateElement("student");
  29. name = xmlDoc.CreateElement("name");
  30. name.InnerText = "Shierly";
  31. age = xmlDoc.CreateElement("age");
  32. age.InnerText = "19";
  33. id = xmlDoc.CreateElement("id");
  34. id.InnerText = "20113210";
  35. student.AppendChild(name);
  36. student.AppendChild(age);
  37. student.AppendChild(id);
  38. root.AppendChild(student);
  39. student = xmlDoc.CreateElement("student");
  40. name = xmlDoc.CreateElement("name");
  41. name.InnerText = "Lili";
  42. age = xmlDoc.CreateElement("age");
  43. age.InnerText = "21";
  44. id = xmlDoc.CreateElement("id");
  45. id.InnerText = "20111110";
  46. student.AppendChild(name);
  47. student.AppendChild(age);
  48. student.AppendChild(id);
  49. root.AppendChild(student);
  50. xmlDoc.AppendChild(root);
  51. //把XML檔案儲存至本地
  52. xmlDoc.Save(filepath);
  53. }
  54. }
這個程式碼執行後就會在目標資料夾中生成一個xml檔案而檔案內容就是1中的那段xml程式碼。 可以看出來 XmlElement 是基本結構單元。也就是xml中的一對<Name></Name>。 1.我們可以對這個結構單元新增屬性:xmlelement.SetAttribute(name,value)。 2.也可以對這個結構單元新增子結構單元:xmlelement.AppendChild(childelement)。 3.如果該結構單元沒有子結構了還可以設定它的內容值:xmlelement.InnerText = value. c.更新xml檔案( 修改第三個學生的名字為Jack )
  1. public void UpdateXml()
  2. {
  3. string filepath = "E:/my.xml";
  4. if (File.Exists(filepath))
  5. {
  6. XmlDocument xmlDoc = new XmlDocument();
  7. //根據路徑將XML讀取出來
  8. xmlDoc.Load(filepath);
  9. //得到team下的所有student節點.
  10. XmlNodeList studentlist = xmlDoc.SelectSingleNode("team").ChildNodes;
  11. //遍歷所有子節點
  12. foreach (XmlElement student in studentlist)
  13. {
  14. XmlNode name = student.SelectSingleNode("name");
  15. if (name.InnerText.Equals("Lili"))
  16. {
  17. name.InnerText = "Jack";
  18. }
  19. }
  20. xmlDoc.Save(filepath);
  21. }
  22. }
請注意:xmlelement.SelectSingleNode(name)是選取該節點下第一個子節點中名字為name的節點。必須是父子,不能隔兩級及以上。 更新結果:
  1. <team name="Dreamer">
  2. <student>
  3. <name>Tom</name>
  4. <age>20</age>
  5. <id>20111234</id>
  6. </student>
  7. <student>
  8. <name>Shierly</name>
  9. <age>19</age>
  10. <id>20113210</id>
  11. </student>
  12. <student>
  13. <name>Jack</name>
  14. <age>21</age>
  15. <id>20111110</id>
  16. </student>
  17. </team>
d.新增xml屬性( 增加一個學生:Sharo,22,20112312 )
  1. public void InsertXml()
  2. {
  3. string filepath = "E:/my.xml";
  4. if (File.Exists(filepath))
  5. {
  6. XmlDocument xmlDoc = new XmlDocument();
  7. //根據路徑將XML讀取出來
  8. xmlDoc.Load(filepath);
  9. XmlNode team = xmlDoc.SelectSingleNode("team");
  10. XmlElement newstudent = xmlDoc.CreateElement("student");
  11. XmlElement name = xmlDoc.CreateElement("name");
  12. name.InnerText = "Sharo";
  13. XmlElement age = xmlDoc.CreateElement("age");
  14. age.InnerText = "22";
  15. XmlElement id = xmlDoc.CreateElement("id");
  16. id.InnerText = "20112312";
  17. //向新隊員新增屬性
  18. newstudent.AppendChild(name);
  19. newstudent.AppendChild(age);
  20. newstudent.AppendChild(id);
  21. //將新隊員新增到團隊裡面
  22. team.AppendChild(newstudent);
  23. xmlDoc.Save(filepath);
  24. }
  25. }
上述程式碼演示了新增節點,其實對節點新增屬性也是一樣的。 更新結果:
  1. <team name="Dreamer">
  2. <student>
  3. <name>Tom</name>
  4. <age>20</age>
  5. <id>20111234</id>
  6. </student>
  7. <student>
  8. <name>Shierly</name>
  9. <age>19</age>
  10. <id>20113210</id>
  11. </student>
  12. <student>
  13. <name>Jack</name>
  14. <age>21</age>
  15. <id>20111110</id>
  16. </student>
  17. <student>
  18. <name>Sharo</name>
  19. <age>22</age>
  20. <id>20112312</id>
  21. </student>
  22. </team>
e.刪除xml節點(刪除Tom學生的資訊)
  1. public void DeleteXml()
  2. {
  3. string filepath = "E:/my.xml";
  4. if (File.Exists(filepath))
  5. {
  6. XmlDocument xmlDoc = new XmlDocument();
  7. //根據路徑將XML讀取出來
  8. xmlDoc.Load(filepath);
  9. XmlNode team = xmlDoc.SelectSingleNode("team");
  10. XmlNodeList studentlist = team.ChildNodes;
  11. foreach(XmlNode student in studentlist)
  12. {
  13. XmlNode name = student.SelectSingleNode("name");
  14. if(name.InnerText.Equals("Tom"))
  15. {
  16. team.RemoveChild(student);
  17. }
  18. }
  19. xmlDoc.Save(filepath);
  20. }
  21. }
可以使用 xmlelement.RemoveAll() 刪除所有子節點 更新結果:
  1. <team name="Dreamer">
  2. <student>
  3. <name>Shierly</name>
  4. <age>19</age>
  5. <id>20113210</id>
  6. </student>
  7. <student>
  8. <name>Jack</name>
  9. <age>21</age>
  10. <id>20111110</id>
  11. </student>
  12. <student>
  13. <name>Sharo</name>
  14. <age>22</age>
  15. <id>20112312</id>
  16. </student>
  17. </team>
f.解析xml檔案
  1. public void LoadXml()
  2. {
  3. string filepath = "E:/my.xml";
  4. if (File.Exists(filepath))
  5. {
  6. XmlDocument xmlDoc = new XmlDocument();
  7. //根據路徑將XML讀取出來
  8. xmlDoc.Load(filepath);
  9. XmlElement team = (XmlElement)xmlDoc.SelectSingleNode("team");
  10. string teamname = team.GetAttribute("name");
  11. Console.WriteLine("這是一個名叫\"" + teamname + "\"的隊伍:");
  12. XmlNodeList studentlist = team.ChildNodes;
  13. Console.WriteLine("一共有" + studentlist.Count + "人");
  14. foreach (XmlNode student in studentlist)
  15. {
  16. XmlNode name = student.SelectSingleNode("name");
  17. XmlNode age = student.SelectSingleNode("age");
  18. XmlNode id = student.SelectSingleNode("id");
  19. Console.WriteLine("姓名:" + name.InnerText + ",年齡:" + age.InnerText + ",學號:" + id.InnerText);
  20. }
  21. xmlDoc.Save(filepath);
  22. }
  23. }
在實際情況中,我們一般在解析xml的時候去給物件相關屬性賦值。相當於是在還原xml中表示的物件資料。 輸出結果:
  1. 這是一個名叫"Dreamer"的隊伍:
  2. 一共有3
  3. 姓名:Shierly,年齡:19,學號:20113210
  4. 姓名:Jack,年齡:21,學號:20111110
  5. 姓名:Sharo,年齡:22,學號:20112312
4.Json使用的簡單介紹.(Json使用需要下載LitJson的包) a.先來看看json程式碼
  1. {
  2. "Name" : "Dreamer",
  3. "Number" : 3,
  4. "Member" :
  5. [
  6. {
  7. "Name" : "Tom",
  8. "Age" : 20,
  9. "Id" : "20111234"
  10. },
  11. {
  12. "Name" : "Jack",
  13. "Age" : 22,
  14. "Id" : "20112312"
  15. }
  16. ]
  17. }
恩這個描述看起來比較熟悉?沒錯,這就是鍵值對的表現方式。相比起xml來說json省略了很多冗餘的表達格式。 仔細看可以發現json的基本結構單元就是以{ }括起來的一組鍵值對,而這個結構單元也可以作為值。而[ ]中括號就表示陣列,陣列的每個元素都是一個結構單元。 鍵值對的表示是 key :value,鍵值對之間用,隔開。 b.生成json程式碼
  1. public void CreateJson()
  2. {
  3. string path = "E:/json.txt";
  4. FileInfo t = new FileInfo(path);
  5. StreamWriter sw = t.CreateText();
  6. StringBuilder sb = new StringBuilder();
  7. JsonWriter writer = new JsonWriter(sb);
  8. //相當於寫下了'{'
  9. writer.WriteObjectStart();
  10. //相當於寫下了"Name":
  11. writer.WritePropertyName("Name");
  12. //相當於寫下了"Dreamer"
  13. writer.Write("Dreamer");
  14. writer.WritePropertyName("Number");
  15. writer.Write("3");
  16. writer.WritePropertyName("Member");
  17. //相當於寫下了'['
  18. writer.WriteArrayStart();
  19. writer.WriteObjectStart();
  20. writer.WritePropertyName("Name");
  21. writer.Write("Tom");
  22. writer.WritePropertyName("Age");
  23. writer.Write("20");
  24. writer.WritePropertyName("Id");
  25. writer.Write("20111234");
  26. //相當於寫下了'}'
  27. writer.WriteObjectEnd();
  28. writer.WriteObjectStart();
  29. writer.WritePropertyName("Name");
  30. writer.Write("Jack");
  31. writer.WritePropertyName("Age");
  32. writer.Write("22");
  33. writer.WritePropertyName("Id");
  34. writer.Write("20112312");
  35. writer.WriteObjectEnd();
  36. //相當於寫下了']'
  37. writer.WriteArrayEnd();
  38. writer.WriteObjectEnd();
  39. sw.WriteLine(sb.ToString());
  40. sw.Close();
  41. }
這段程式碼就是生成上面json程式碼的生成程式碼。 很顯然,json生成的程式碼更像是html這類程式碼一樣,按照生成檔案的格式呼叫對應的API。不過,json有更好的方式,它可以直接對物件序列化。 看下面的例子:
  1. using UnityEngine;
  2. using LitJson;
  3. public class A
  4. {
  5. public string name = "yzl";
  6. public int old = 20;
  7. }
  8. public class Test : MonoBehaviour
  9. {
  10. void Start()
  11. {
  12. A a = new A();
  13. Debug.Log(JsonMapper.ToJson(a));
  14. }
  15. }
觀察控制檯輸出:{"name":"yzl","old":20} 發現,json可以直接對物件裡面的屬性序列化生成對應的json檔案。這就是很方便的地方了。當然,xml也有這個功能,但是需要對類的屬性新增節點標籤。相比json要麻煩一些。 c.json的增刪改( 增加隊伍地址屬性,刪除隊伍人數屬性,修改隊名 )
  1. using UnityEngine;
  2. using System.Collections;
  3. using System;
  4. using System.Collections.Generic;
  5. using LitJson;
  6. using System.IO;
  7. public class Test : MonoBehaviour
  8. {
  9. void Start()
  10. {
  11. StreamReader sr = File.OpenText("E:/json.txt");
  12. string strline = sr.ReadToEnd();
  13. JsonData jd = JsonMapper.ToObject(strline);
  14. //修改隊名
  15. jd["Name"] = "Winer";
  16. //新增隊伍地址屬性
  17. jd["Address"] = "Sichuan";
  18. //刪除隊伍人數屬性
  19. ((IDictionary)jd).Remove("Number");
  20. Debug.Log(jd.ToJson());
  21. sr.Close();
  22. }
  23. }
可以看出來json使用起來要比xml方便許多,解析的使用方法和C#的字典類似。 d.json的解析檢視
  1. using UnityEngine;
  2. using System.Collections;
  3. using System;
  4. using System.Collections.Generic;
  5. using LitJson;
  6. using System.IO;
  7. public class Test : MonoBehaviour
  8. {
  9. void Start()
  10. {
  11. StreamReader sr = File.OpenText("E:/json.txt");
  12. string strline = sr.ReadToEnd();
  13. JsonData jd = JsonMapper.ToObject(strline);
  14. Debug.Log("隊伍名:" + jd["Name"]);
  15. Debug.Log("隊伍人數:" + jd["Number"]);
  16. for (int i = 0; i < jd["Member"].Count; i++)
  17. {
  18. Debug.Log("姓名:" + jd["Member"][i]["Name"] + ",年齡:" + jd["Member"][i]["Age"] + ",學號:" + jd["Member"][i]["Id"]);
  19. }
  20. sr.Close();
  21. }
  22. }
輸出結果:
隊伍名:Dreamer
隊伍人數:3
姓名:Tom,年齡:20,學號:20111234
姓名:Jack,年齡:22,學號:20112312
好了基本上,xml和json的簡單使用就介紹到這裡,之後我提供幾個序列化實戰例子:1.場景的xml/Json儲存. 2.遊戲的xml加密存檔。