unity进阶学习笔记:json和xml

news/2025/3/1 2:00:16/

1早期的数据格式

在早期程序开发中一个简单且常用的数据格式为CSV。该格式单纯依靠逗号来分割数据。目前windows的office依然支持CSV解析,我们可以试着新建一个txt文件,在里面加入逗号分隔的信息:

a, 1, 15, 30, true

将txt文件后缀改为csv,可以看到系统自动生成了一个excel表格,由空格分隔的每一项都成了表格的一个单元。但显然这种方法可读性很差,因此对于存储大量数据不常用

2 json

json是一种“数组+对象” 的数据存储方式,其中[ ]内为数组,{ }内为对象,例如

{"Persons":[{"name":"a","age":18},{"name":"b","age":17}]
}

unity自带json数据创建和解析的功能JsonUtility。

示例:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;[Serializable]
public class Person {public string name;public int age;
}[Serializable]
public class Persons {public Person[] persons;
}public class JsonUtilityTest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Person person = new Person();person.name = "a";person.age = 18;Person person2 = new Person();person2.name = "b";person2.age = 17;Persons persons = new Persons();persons.persons = new Person[] {person, person2};string jsonStr = JsonUtility.ToJson(persons);Debug.Log(jsonStr);Persons ps = JsonUtility.FromJson<Persons>(jsonStr);foreach (Person p in ps.persons) {Debug.Log(p.name);}}}

1

using System;

要使用JsonUtility工具,要先在文件中引入System

2

[Serializable]
public class Person {public string name;public int age;
}[Serializable]
public class Persons {public Person[] persons;
}

这里我们创建两个类Person和Persons用于示例。在类前面的标记[Serializable]代表可序列化,只有带有该标记的类才能转化为json格式

3

string jsonStr = JsonUtility.ToJson(persons);

在我们创建并赋值Persons对象后,使用JsonUtility.ToJson()方法即可将对象自动转化为json文件,其内容如下:
{“persons”:[{“name”:“a”,“age”:18},{“name”:“b”,“age”:17}]}

Persons ps = JsonUtility.FromJson<Persons>(jsonStr);

要解析json文件,我们使用方法JsonUtility.FromJson<类型>()得到json文件最外层的数据类型,然后即可对该数据进行层层拆包得到里面的数据

除了系统自带的JsonUtility方法,还有很多常用的第三方json数据处理方法,如LitJson

下载LitJson的dll文件后,在unity Assets文件夹下面创建Plugins文件夹,并把LitJson.dll放入该文件夹。在C#脚本中引入LitJson即可使用LitJson文件

LitJson使用示例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LitJson;public class Heros {public Hero[] heros;
}public class Hero {public string name;public int age;
}public class TestLitJson : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){fun3();}void fun1() {Hero hero1 = new Hero();hero1.name = "Superman";hero1.age = 35;Hero hero2 = new Hero();hero2.name = "Batman";hero2.age = 38;Heros heros = new Heros();heros.heros = new Hero[] {hero1, hero2};string jsonStr = JsonMapper.ToJson(heros);Debug.Log(jsonStr);Heros hs = JsonMapper.ToObject<Heros>(jsonStr);Debug.Log(hs.heros[1].name);}// using JsonData typevoid fun2() {JsonData jd1 = new JsonData();jd1.SetJsonType(JsonType.Object);jd1["name"] = "Superman";jd1["age"] = 35;JsonData jd2 = new JsonData();jd2.SetJsonType(JsonType.Object);jd2["name"] = "Batman";jd2["age"] = 38;JsonData jds = new JsonData();jds.SetJsonType(JsonType.Array);jds.Add(jd1);jds.Add(jd2);JsonData heroJd = new JsonData();heroJd.SetJsonType(JsonType.Object);heroJd["heros"] = jds;Debug.Log(heroJd.ToJson());}void fun3() {string jsonStr = "{'heros':[{'name':'Superman','age':35},{'name':'Batman','age':38}]}";JsonData herosJd = JsonMapper.ToObject(jsonStr);JsonData heros = herosJd["heros"];foreach (JsonData heroJd in heros) {Debug.Log(heroJd["name"].ToString() + " " + (int)heroJd["age"]);}}
}

1

    void fun1() {Hero hero1 = new Hero();hero1.name = "Superman";hero1.age = 35;Hero hero2 = new Hero();hero2.name = "Batman";hero2.age = 38;Heros heros = new Heros();heros.heros = new Hero[] {hero1, hero2};string jsonStr = JsonMapper.ToJson(heros);Debug.Log(jsonStr);Heros hs = JsonMapper.ToObject<Heros>(jsonStr);Debug.Log(hs.heros[1].name);}

和JsonUtility类似,LitJson可以根据一个类创建json文件,使用JsonMapper.ToJson文件

要解析Json文件,使用JsonMapper.ToObject方法,可得到Json文件解析后的对象

2

    // using JsonData typevoid fun2() {JsonData jd1 = new JsonData();jd1.SetJsonType(JsonType.Object);jd1["name"] = "Superman";jd1["age"] = 35;JsonData jd2 = new JsonData();jd2.SetJsonType(JsonType.Object);jd2["name"] = "Batman";jd2["age"] = 38;JsonData jds = new JsonData();jds.SetJsonType(JsonType.Array);jds.Add(jd1);jds.Add(jd2);JsonData heroJd = new JsonData();heroJd.SetJsonType(JsonType.Object);heroJd["heros"] = jds;Debug.Log(heroJd.ToJson());}

除了利用对象创建Json文件,LitJson还支持不创建对象,直接使用JsonData创建Json文件。JsonData类型包括了Int Double Boolean Array Object等常用类型。

在上面代码中,我们创建JsonData类jd1,之后使用SetJsonType将其类型设为Object(这一句可以省略,LitJson会自动判断数据类型)。

对于Object类,使用键值对来添加值,对于数组,使用Add方法添加元素

void fun3() {string jsonStr = "{'heros':[{'name':'Superman','age':35},{'name':'Batman','age':38}]}";JsonData herosJd = JsonMapper.ToObject(jsonStr);JsonData heros = herosJd["heros"];foreach (JsonData heroJd in heros) {Debug.Log(heroJd["name"].ToString() + " " + (int)heroJd["age"]);}}

JsonMapper.ToObject方法除了支持使用泛型将Json数据解析成特定类型,还可以不使用泛型,解析完的数据默认类型全部为JsonData类型,包括内部的所有类的数据。因此在Debug.Log中我们要先将name和age分别转换为String和int类型

2 xml

xml是一种常用的标记语言,语法和html很类似,都由节点组成。我们以下面例子来讲解

<?xml version="1.0" encoding="utf-8"?>
<root><heros><hero id="1"><name>Superman</name><age>35</age></hero><hero id="2"><name>Batman</name><age>37</age></hero><hero id="3"><name>Spiderman</name><age>30</age></hero></heros>
</root>

1

<?xml version="1.0" encoding="utf-8"?>

这一句用于声明xml格式,标明版本和使用编码

2

 <root></root>

为根节点,根节点只能有一个。其他所有节点在根节点内部。

3 <hero id="1"> <name>Superman</name> <age>35</age> </hero>

对于一个节点,里面要么保存字符串值,要么保存一个子节点(不可同时保存)。节点尖括号内部可以添加属性(即为节点变量),属性值必须包括在""里面

解析xml文件(方法1)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml;public class XMLTest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){parseXml();}void parseXml() {// xml文档类XmlDocument doc = new XmlDocument();doc.Load(Application.dataPath + "/XML/testXml.xml");// rootXmlElement rootEle = doc.LastChild as XmlElement;   // herosXmlElement herosEle = rootEle.FirstChild as XmlElement;// heorforeach(XmlElement heroEle in herosEle.ChildNodes) {string id = heroEle.GetAttribute("id");string name = heroEle.ChildNodes[0].InnerText;string age = heroEle.ChildNodes[1].InnerText;Debug.Log(id + name + age);}}
}

在文件开头要引入System.Xml以使用xml工具

xml文件类型称为XmlDocument。我们先创建新的XmlDocument对象并导入刚才创建的xml文件

LastChild FirstChild方法用于获取节点的第一个和最后一个元素。ChildNodes数组保存节点里面所有元素。获取到的元素类型XmlNode,该类型为XmlElement的子类,因此获取到XmlElement需要进行类型转换

GetAttribute方法用于获取节点内的属性。要得到节点内保存的值使用方法InnerText

解析xml文件(方法2)

    void parseXml2() {XmlDocument doc = new XmlDocument();doc.Load(Application.dataPath + "/XML/testXml.xml");XmlNodeList list = doc.SelectNodes("/root/heros/hero/name");foreach (XmlElement element in list) {Debug.Log(element.InnerText);}}

除了常规从根目录进行解析,我们可以实现XPath直接通过文件路径访问到特定的节点。在上面例子中,SelectNodes()根据给出的XPath路径找到所有符合该路径的节点,得到结果Superman,Batman,Spiderman

XPath路径还有几种特殊写法
1 相对路径

XmlNodeList list = doc.SelectNodes(“//name”);

//代表使用相对路径。此时我们会查找到所有名为name的节点。不过直接使用相对路径查找要遍历所有节点,效率较低

2 访问第几个节点

XmlNodeList list = doc.SelectNodes(“//heros/hero[last()-1]/name”)

在节点后面[ ]中可以输入要访问第几个节点,注意第一个节点编号为1不是0.last()为最后一个节点的编号

3 访问前几个节点

XmlNodeList list = doc.SelectNodes(“//heros/hero[position()< 3]/name”);

在[ ]中position()可以用于访问前几个节点,上面的position()< 3代表访问1,2节点

4 根据节点属性值访问节点

XmlNodeList list = doc.SelectNodes(“//heros/hero[@id=2]/name”);

在[ ]中@id=2代表访问所有有id属性的节点中,id值为2的节点。如果直接为@id代表访问所有有id属性的节点

构建XML文件

    void createXml() {XmlDocument doc = new XmlDocument();XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", "");doc.AppendChild(dec);XmlElement rootEle = doc.CreateElement("root");doc.AppendChild(rootEle);XmlElement herosEle = doc.CreateElement("heros");rootEle.AppendChild(herosEle);string[] names = new string[] {"Superman", "Batman", "Spiderman"};string[] ages = new string[] {"35", "37", "20"};for (int i = 0; i < 3; i++) {XmlElement heroEle = doc.CreateElement("hero");herosEle.AppendChild(heroEle);XmlElement nameEle = doc.CreateElement("name");nameEle.InnerText = names[i];heroEle.AppendChild(nameEle);XmlElement ageEle = doc.CreateElement("age");ageEle.InnerText = ages[i];heroEle.AppendChild(ageEle);XmlAttribute id = doc.CreateAttribute("id");id.Value = i + "";heroEle.Attributes.Append(id);}doc.Save(Application.dataPath + "/XML/test2.xml");}

1

XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", "");

这一句用于创建XML声明,也就是XML文件开头的<?xml version="1.0" encoding="utf-8"?>

2

XmlElement rootEle = doc.CreateElement("root");
doc.AppendChild(rootEle);

创建根节点名称root,并在文件根目录添加改节点。后面添加节点的语句写法相同

3

XmlElement nameEle = doc.CreateElement("name");
nameEle.InnerText = names[i];
heroEle.AppendChild(nameEle);

对有内容的节点,使用InnerText来填充内容,再把该节点加入到其父节点。

4

XmlAttribute id = doc.CreateAttribute("id");
id.Value = i + "";
heroEle.Attributes.Append(id);

要为一个节点添加属性,首先创建XmlAttribute对象,再把该对象加入节点的Attribute中,方法和添加子节点类似

5

doc.Save(Application.dataPath + "/XML/test2.xml");

保存XML文件到指定路径


http://www.ppmy.cn/news/71220.html

相关文章

【计算机网络】总结复习(1)

本文主要记录在看小林coding 时的一些体会&#xff0c;会记录一些我认为重要的知识点以及感受 网络基础篇 osi 七层协议 tcp/ip 四层协议 应用层 传输层 网络层 网络接口层 实际场景&#xff1a; 输出网址 到 网页显示 过程url 解析&#xff08;协议web 服务器 数据源路径…

用项目管理思维来过5·20,真实太酷啦!

明天就是一年一度的520啦&#xff0c;阿道单身多年的同事刚京在四月成功使用SWOT分析模型相亲成功&#xff0c;牵手女嘉宾。二人眼看着就要迎来在一起后的第一个节日520&#xff0c;刚京却因为没有头绪而陷入了不知所措的焦虑。 团队成员齐上阵&#xff0c;用项目管理思维&…

【linux】:获取系统内存及内存清理操作(python)

获取系统内存操作&#xff08;python&#xff09; 1.os.statvf()函数介绍2.系统剩余内存获取&#xff1a;3.文件清理 1.os.statvf()函数介绍 os.statvfs() 方法用于返回包含文件描述符fd的文件的文件系统的信息。 语法 statvfs()方法语法格式如下&#xff1a; os.statvfs([pa…

【Java】jieba结巴分词器自定义分词词典 超详细完整版

发现一款很轻量好用的分词器->结巴分词器 分享给大家 不仅可以对常规语句分词&#xff0c;还可以自定义分词内容&#xff0c;很强大&#xff01;&#xff01; 源码地址&#x1f449;&#xff1a;https://github.com/huaban/jieba-analysis 简单使用 如果是常规的语句&#…

基于 KONOS 编写一个部门级的前端框架

01 什么是 konos 现在对于前端框架的定义越来越广泛了&#xff0c;在前端工程化中的某一个环节的特定方案&#xff0c;都可泛称为一个前端框架。 konos 是一个插件化的前端框架基座&#xff0c;如果你对 umi 有所了解的话&#xff0c;可以把它当作一个没有任何功能的 umi core …

《终身成长》笔记一——人的表现不能只根据一次评估来断定

目录 内容简介 经典摘录 1、会有人热爱失败吗 2、人为什么会有不同 3、两种思维模式对人意味着什么 4、 两种思维模式之下的不同生活 5、【成长型思维模式】下你将会看到什么 6、但教书育人不就是学校要做的吗&#xff1f;他们来到学校&#xff0c;就是为了学习如何去做…

gtest安装

sudo apt update sudo apt install build-essential cmake git clone https://github.com/google/googletest.git cd googletest mkdir build cd build cmake … make ./bin/gtest_unittests&#xff08;测试一下gtest是否正常&#xff0c;但我这bin下没有内容&#xff09; sud…

MySQL之InnoDB表空间

前言 本文章收录在MySQL性能优化原理实战专栏&#xff0c;点击此处查看更多优质内容。 本文摘录自 ▪ 小孩子4919《MySQL是怎样运行的&#xff1a;从根儿上理解MySQL》 通过前边的内容&#xff0c;相信大家都知道了表空间是一个抽象的概念&#xff0c;对于系统表空间来说&am…