Unity - 数据持久化 - JSON
什么是数据持久化
数据持久化就是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。
通俗解释:将游戏数据存储到硬盘,硬盘中的数据读取到游戏中,即传统意义上的存盘。
Json 介绍
全称: JavaScript 对象简谱(JavaScript Object Notation)
特点:
- Json 是国际通用的一种轻量级的数据交换格式
- 主要用于网络通讯中传输数据,或本地数据存储和读取
- 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率
用途:
我们一般使用 Json 文件来记录和传输数据。Json 文档就是使用 Json 格式配置填写的文档,后缀一般为 .json
。在游戏中,可以把游戏数据按照 Json 格式标准存储在 Json 文档中,再将 Json 文档存储在硬盘上或者传输给远端,达到数据持久化或数据传输的目的。
Json 和 Xml 的异同
共同点:
- 都是纯文本
- 都有层级结构
不同点:
- Json 配置更简单,在某些情况下读写更快速。
Json 优缺点
优点:
- 跨平台:Json 是国际通用规则,可以在不同平台(游戏、软件、网页等)和操作系统中使用。
- 结构清晰:文件结构清晰易懂,非常容易编辑和理解,可用于网络通信交换数据。
- 数据配置:可以利用 Excel 转 Json 帮助策划进行数据配置。
缺点:
- 重复工作量大:自定义数据类都需要自己去实现存储读取的功能,且代码相似度较高。
- 数据容易被修改:只要找到文件位置,就可以轻易地进行数据修改。
Json 的主要用处
- 网络游戏:存储客户端简单不重要数据,传输信息。
- 单机游戏:存储游戏相关数据,配置游戏数据。
学习 Json 的意义和目标
- 增加一种存储和传输数据的选择。
- 增加一种配置数据的方法(具体会结合 UI 第三部曲讲解)。
目标:
- 掌握 Json 的基础规则。
- 掌握 C#读取存储 Json 文件。
Json 配置规则
用什么编辑 Json 文件?
任何能打开文档的软件都能打开 Json 文件。常用的编辑 Json 文件的方式包括:
- 系统自带:记事本、写字板
- 通用文本编辑器:Sublime Text 等等
- 网页上的 Json 编辑器
推荐使用 VSCode。
创建 Json 文件
直接右键创建文本,后缀改为 .json
,选择自己喜欢的用于编辑 Json 的软件进行文本编辑。
JSON 语法规则
符号含义:
- 大括号 {} —— 对象
- 中括号 [] —— 数组
- 冒号 : —— 键值对应关系
- 逗号 , —— 数据分割
- 双引号 “” —— 键名/字符串
键值对表示:
“键名”: 值内容
值类型:
- 数字(整数或浮点)
- 字符串
- true 或 false
- 数组
- 对象
- null
注意:Json 不支持注释(发明者要求 Json 应该简洁)。
示例
1 | public class CCLing{ |
变量名就是键,键用 ""
表示;冒号后面的内容就是值,值的类型不同表示不同。
注意:字典的键值对都是使用 ""
表示。
Json 文件示例
1 | { |
配置 Json 文档时的注意事项
- 如果数据表示对象,那么最外层有大括号。
- 一定是键值对形式。
- 键一定是字符串格式。
- 键值对用逗号分开。
- 数组用
[]
包裹。 - 对象用
{}
包裹。
Excel 转 Json
在游戏开发中,使用 Excel 配置数据可以方便策划人员进行数据管理。通过在线工具,可以将 Excel 中的数据转换为 JSON 格式,以便将数据读取到内存中进行使用。
在 Excel 表中配置游戏数据
- 列标题为属性名
- 列元素为数据
使用在线工具转换为 JSON
- 使用在线 Excel、CSV 转 JSON 格式工具
- 将配置好的 Excel 表导入工具中,转换为 JSON 格式
优点:
- 方便策划人员配置:Excel 界面直观,易于使用,策划人员可以轻松编辑和管理数据。
- 简化数据转换:通过在线工具,可以快速将 Excel 数据转换为 JSON,减少手动编码的工作量。
- 提高数据一致性:使用统一的 Excel 模板,可以保证数据格式的一致性,减少错误。
- 便于数据持久化和传输:转换为 JSON 格式后,数据可以方便地存储在硬盘上或传输给远端服务器,实现数据持久化或网络传输。
JsonUtility 序列化/反序列化
JsonUtility 是什么?
JsonUtlity 是Unity 自带的用于解析 Json 的公共类
它可以:
- 将内存中对象序列化为 Json 格式的字符串
- 将 Json 字符反序列化为类对象
在文件中读写字符串
使用 File.WriteAllText
和 File.ReadAllText
需要使用命名空间 System.IO
。
1 | //1、存储字符串到指定路径文件中 |
使用 JsonUtility 进行序列化
序列化:把内存中的数据,存储到硬盘上。
使用 JsonUtility.ToJson(obj)
方法即可。
注意:
- float 序列化时看起来会有一些误差(实际读出来就正常了)
- 自定义类需要加上序列化特性
[System.Serializable]
- 想要序列化私有变量,需要加上特性
[SerializeField]
- JsonUtlity 不支持字典序列化(和 XmlSerializer 一样)
- JsonUtlity 存储 null 对象不会是 null,而是默认值数据
1 | Data d = new Data(); |
使用 JsonUtility 进行反序列化
反序列化:把硬盘上的数据读取到内存中
使用 JsonUtility.FromJson(string, type)
方法即可(支持泛型)
1 | ret = File.ReadAllText(Application.streamingAssetsPath + "/Test.json"); |
注意:如果 Json 当中内容少了,不会报错,会设置为类型默认值。
知识点五 注意事项
JsonUtility 无法直接读取数据集合,可以使用一个类包裹来读取
1
List<Data> datas = JsonUtility.FromJson<List<Data>>(ret); //无法读取
文本编码格式需要是 UTF-8,不然无法加载
总结
- 必备知识点一 File 存读专符串的方法 ReadAllText 和 writeAllText
- JsonUtlity 提供的序列化反序列化方法 ToJson 和 FromJson
- 自定义类需要加上序列化特性
[System.Serializable]
- 私有保护成员需要加上
[serializeField]
- JsonUtlity 不支持字典
- JsonUtlity 不能直接将数据反序列化为数据集合
- Json 文档编码格式必须是 UTF-8
LitJson 序列化
知识点一 LitJson 是什么
它是一个第三方库,用于处理 Json 的序列化和反序列化
LitJson 是 C# 编写的,体积小、速度快、易于使用
它可以很容易的嵌入到我们的代码中
只需要将 LitJson 代码拷贝到工程中即可
知识点二 获取 LitJson
- 前往 LitJson 官网
- 通过官网前往 GitHub 获取最新版本代码
- 将代码拷贝到 Unity 工程中即可开始使用 LitJson
知识点三 序列化
- 相对 JsonUtlity 不需要加特性
- 不能序列化私有变量
- 支持字典类型,字典的键建议都是字符串因为 Json 的特点 Json 中的键会加上双引号
- 需要引用 LitJson 命名空间
- LitJson 可以准确的保存 null 类型
使用 JsonMapper.ToJson(obj)
,返回字符串,然后将字符串写入文件即可。
1 | DataInfo data = new DataInfo(); |
知识点四 反序列化
使用 JsonMapper.ToObject(字符串)
,支持泛型
注意:
- 类结构需要无参构造函数,否则反序列化时报错
- 字典虽然支持但是键在使用为数值时会有问题需要使用字符串类型
1 | str = File.ReadAllText(Application.streamingAssetsPath + "/Test2.json"); |
知识点五 注意事项
- LitJson 可以直接读取数据集合
- 文本编码格式需要是
UTF-8
,不然无法加载
总结
- LitJson 提供的序列化反序列化方法
JsonMapper.ToJson
和ToObject
(支持泛型) - LitJson 无需加特性
- LitJson 不支持私有变量
- LitJson 支持字典序列化反序列化
- LitJson 可以直接将数据反序列化为数据集合
- LitJson 反序列化时自定义类型需要无参构造
- json 文档编码格式必须是 UTF-8
JsonUtility 和 LitJson 对比
相同点
- 他们都是用于 Json 的序列化反序列化
- Json 文档编码格式必须是 UTF-8
- 都是通过静态类进行方法调用
不同点
- JsonUtility 是 Unity 自带,LitJson 是第三方需要引用命名空间
- JsonUtility 使用时自定义类需要加特性,LitJson 不需要
- JsonUtility 支持私有变量(加特性),LitJson 不支持
- JsonUtility 不支持字典,LitJson 支持(但是键只能是字符串)
- JsonUtility 不能直接将数据反序列化为数据集合(数组字典),LitJson 可以
- JsonUtility 对自定义类不要求有无参构造,LitJson 需要
- JsonUtility 存储空对象时会存储默认值而不是 null,LitJson 会存 null
使用建议
根据实际需求
建议使用 LitJson
原因:LitJson 不用加特性,支持字典,支持直接反序列化为数据集合,存储 null 更准确