Unity之数据持久化——Json

Unity数据持久化设计二 JSON JSON是JavaScript Object Notation的简称,是一种轻量级的数据交换格式,主要是运用再网络通信数据传输中或者是本地数据存储和读取的操作。JSON易于阅读和编写,同时也易于机器解析和生成,并能够有效的提高网络传输效率。以上内容介绍了JsonUnitily与LitJson的基础使用、封装使用及实际项目运用方法,两种方法也是有各自的优劣势及使用注意点,当然目前的也不是最好的使用方法,有更好方法的可以选用更优选项。 阅读详情

1、Json是什么

JavaScript对象简谱(JavaScript Object Notation)

json是国际通用的一种轻量级的数据交换格式,主要在网络通讯中用于传输数据,或本地数据存储和读取,易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率

游戏中可以把游戏数据按照Json的格式标准存储在Json文档中,再将Json文档存储在硬盘上或者传输给远端,达到数据持久化或者数据传输的目的

Json和Xml的异同:

共同点:都是纯文本,都有层级结构,都具有描述性

不同点:Json配置更简单,Json在某些情况下读写更快速

注意:在以下代码中我存储的文件地址是StreamingAssets文件夹,但通常是使用Application.persistentDataPath,因为StreamingAssets文件夹在某些平台(例如Android)是不可写的

2、编辑Json文件的方式

(1)系统自带——记事本、写字板

(2)通用文本编辑器——Sublime Text等

(3)网页Json编辑器

我用的是vs code,可以直接编辑json文件

3、基础语法

注释和C#中注释方式一致,但是需要设置为”Json with Comments“ 的形式(在vs code右下角设置)

语法规则:

符号含义:

大括号{}对象
中括号[]数组
冒号:键值对对应关系
逗号,数据分割
双引号“”键名/字符串
值类型数字(整数或浮点)、字符串、true或false、数组、对象、null

Json格式是一种键值对结构,表示为:“键名”:值内容

以C#代码为例:

class ClassInfo {
    public string name;
    public int age;
    public bool sex;
    public List<int> ids;
    public List<Person> students;
    public Home home;
    public Person son;
}

class Person {
    public string name;
    public int age;
    public bool sex;
}

class Home {
    public string address;
    public string street;
}

 将ClassInfo类转换为Json格式为:

// 大括号包裹的代表一个对象
{
    // 冒号代表键值对的对应关系
    // 逗号就是分割成员变量的间隔符
    // Json当中的键一定要用双引号包裹,值是否用双引号由类型决定
    "name": "Waylon",
    "age": 18,
    "sex": true,
    "testF": 1.4,    // 用于测试支持浮点类型
    // 中括号代表数组
    "idx": [1,2,3,4],
    "students": [
        {"name": "Hong", "age": 5, "sex": false},
        {"name": "Ming", "age": 6, "sex": true},
        {"name": "Qiang", "age": 8, "sex": true}
        // 注意:最后一项不要加逗号,否则解析可能会出问题!!!
    ],
    "home": {
        "address": "Cheng",
        "street": "Chun"
    },
    "son": null
}

字典的键(数字)会变成双引号字符串形式,转换时要注意!!!

“dic":{“1”:“123”,“key":{"id":1, "num": 3}}

同时,Json中不会对private, protected进行解释

4、Excel转Json

暂时可以通过在线转换工具:https://www.bejson.com/json/col2json/

然后【下载Json代码】,转换结果不一定准确

5、JsonUtility序列化

(1)、JsonUtility是什么

JsonUtility是Unity自带的用于解析Json的公共类,它可以:

i、将内存中对象序列化为Json格式的字符串

ii、将Json字符串反序列化为类对象

(2)在文件种存读字符串

i、存储字符串到指定路径文件中

// 参数一:存储路径
// 必须是存在的文件路径,如果没有对应文件夹,会报错
// 参数二:存储的字符串内容
File.WriteAllText(Application.streamingAssetsPath+ "/Test.json", "测试存储的json文件");
// 如果Json文件夹不存在则会报错
// File.WriteAllText(Application.streamingAssetsPath+ "/Json/Test.json", "测试存储的json文件");

ii、在指定路径文件中读取字符串

// 参数一:读取路径
// 参数二:编码格式(可选)
string str = File.ReadAllText(Application.streamingAssetsPath+ "/Test.json");

(3)使用JsonUtility进行序列化

序列化就是把内存中的数据存储到硬盘上,方法是通过API:JsonUtility.ToJson(对象)

以以下类对象举例:

class Student {
    public int age;
    public string name;

    public Student(int age, string name) {
        this.age = age;
        this.name = name;
    }
}

class Person {
    public string name;
    public int age;
    public bool sex;
    public float testF;
    public double testD;

    public int[] ids;
    public List<int> ids2;
    public Dictionary<int, string> dic;
    public Dictionary<string, string> dic2;

    public Student s1;
    public List<Student> s2;

    private int privateI = 1;
    protected int protectedI = 2;
}

然后对该数据类进行序列化 

Person p = new Person();
p.name = "Well";
p.age = 19;
p.sex = true;
p.testF = 1.3f;
p.testD = 1.3;

p.ids = new int[] { 1, 2, 3, 4 };
p.ids2 = new List<int>() { 1, 2, 3, 4 };

p.dic = new Dictionary<int, string>() { { 1, "123" }, { 2, "123" } };
p.dic2 = new Dictionary<string, string>() { { "1", "123" }, { "2", "123" } };

p.s1 = new Student(1, "Hong");
p.s2 = new List<Student>() { new Student(2, "Ming"), new Student(3, "Qiang") };

// JsonUtility.ToJson()可以把类对象序列化为json字符串
string jsonStr = JsonUtility.ToJson(p);
File.WriteAllText(Application.streamingAssetsPath+ "/Person.json", jsonStr);

序列化之后的Json文件存储的是:

{"name":"Well","age":19,"sex":true,"testF":1.2999999523162842,"testD":1.3,"ids":[1,2,3,4],"ids2":[1,2,3,4]}

可以发现,字典、Student、私有、保护数据没有存储

注意:  

  • float序列化时会看来有一些误差,但读取的时候不会有影响
  • 自定义类需要加上序列化特性[System.Serializable],最外层的类不用添加
[System.Serializable]
class Student {
    public int age;
    public string name;

    public Student(int age, string name) {
        this.age = age;
        this.name = name;
    }
}

然后Json中内容是:

{"name":"Well","age":19,"sex":true,"testF":1.2999999523162842,"testD":1.3,"ids":[1,2,3,4],"ids2":[1,2,3,4],"s1":{"age":1,"name":"Hong"},"s2":[{"age":2,"name":"Ming"},{"age":3,"name":"Qiang"}]}
  • 想要序列化私有变量,需要加上特性[SerializeField]
[SerializeField] private int privateI = 1;
[SerializeField] protected int protectedI = 2;

结果为:

{"name":"Well","age":19,"sex":true,"testF":1.2999999523162842,"testD":1.3,"ids":[1,2,3,4],"ids2":[1,2,3,4],"s1":{"age":1,"name":"Hong"},"s2":[{"age":2,"name":"Ming"},{"age":3,"name":"Qiang"}],"privateI":1,"protectedI":2}
  • JsonUtility不支持字典
  • JsonUtility存储null对象不会是null,而是默认的数据

例如:令 s1=null,那么Json文件中存储的是:"s1":{"age":0,"name":""}

(4)JsonUtlity 反序列化

反序列化就是把硬盘上的数据读取到内存中,方法是通过API:JsonUtility.FromJson(字符串) 

反序列化时是通过类的成员名与json文件中的键名进行匹配赋值

注意:如果Json中数据少了,读取到内存中类对象时不会报错,例如对上面的内容进行反序列化:

jsonStr = File.ReadAllText(Application.persistentDataPath + "/Person.json");
// 方法一:
Person p2 = JsonUtility.FromJson(jsonStr, typeof(Person)) as Person;
// 方法二:
Person p3 = JsonUtility.FromJson<Person>(jsonStr);

 那么结果显示如下,可以发现字典类的对象是为null的

(5)JsonUtility注意事项

  • JsonUtility无法直接读取数据集合

例如一个car.json文件中是这样的:

[
    {"id":1, "speed":6},
    {"id":2, "speed":10}
]

然后对应的对象是:

class Car {
    public int id;
    public int speed;
}

那么是不能够将其直接反序列化到List<Car>中的,必须将List<Car>包裹在一个对象中,例如一个类中有一个List<Car> listCar成员,对Car加上[System.Serializable]特性,同样的,要将json文件用大括号包裹:

{
    "listCar":[
        {"id":1, "speed":6}
        {"id":2, "speed":10}
     ]
}
  • 文本编码格式需要是UTF-8,不然无法加载

6、LitJson 

(1)LitJson是什么

第三方库,用于Json的序列化与反序列化,LitJson是C#编写,体积小、速度快、易于使用,它可以很容易地嵌入到代码中,只需要将LitJson代码拷贝到工程中即可

(2)获取LitJson

前往LitJson官网

通过官网前往Github获取最新版本代码

将src/LitJson的代码拷贝到Unity工程中,即可开始使用LItJson

(3)使用LitJson进行序列化

方法:JsonMapper.ToJson(对象)

注意:

  • 相对JsonUtility不需要加特性
  • 不能序列化私有变量
  • 支持字典类型
  • 需要引用LitJson命名空间
  • LitJson可以保存 null 类型

使用和上面同样的例子,但是要把上面的对象、成员的特性移除(因为这些特性是针对JsonUtility的),然后调用:

string jsonStr = JsonMapper.ToJson(p);
File.WriteAllText(Application.streamingAssetsPath + "/Person.json", jsonStr);

结果为:

{"name":"Well","age":19,"sex":true,"testF":1.3,"testD":1.3,"ids":[1,2,3,4],"ids2":[1,2,3,4],"dic":{"1":"123","2":"123"},"dic2":{"1":"123","2":"123"},"s1":null,"s2":[{"age":2,"name":"Ming"},{"age":3,"name":"Qiang"}]}

可以发现,字典能够存储(字典的键都是字符串),同时null能够表示,但是私有、保护变量无法存储,如果存储的有中文,表示方法与JsonUtility也不一样

(4)使用LitJson进行反序列化

方法:JsonMapper.ToObject(字符串)

jsonStr = File.ReadAllText(Application.streamingAssetsPath + "/Person.json");

方法一:

// JsonData是LItJson提供的类对象,可以用键值对的形式访问其中的内容
JsonData data = JsonMapper.ToObject(jsonStr);
print(data["name"]);
print(data["age"]);

方法二:

Person p2 = JsonMapper.ToObject<Person>(jsonStr);

但其实现在方法二是会报错的

ArgumentException: The value '1' is not of type 'System.Int32' and cannot be used in this generic collection.

因为json文本中字典存储的键都是字符串的形式,与Person类中字典键的int不匹配

然后把Person类中的dic字典注释,继续会有另一个报错:

MissingMethodException: Default constructor not found for type Lesson2+Student

这是因为Student类中没有无参构造函数,在其中添加无参构造后就可以正常反序列化

注意:

  • 类结构需要无参构造函数,否则反序列化报错
  • 字典虽然支持,但是键在使用为数值时会有问题,需要使用字符串类型

(5)注意事项

  • LitJson可以直接读取数据集合

还是以car为例:

jsonStr = File.ReadAllText(Application.streamingAssetsPath + "/car.json");

Car[] arr = JsonMapper.ToObject<Car[]>(jsonStr);
List<Car> arr2 = JsonMapper.ToObject<List<Car>>(jsonStr);

这样是可以直接转化的

如果需要直接转字典,假设一个字典数据dic.json为:

{
    "name": 1,
    "name2": 2,
    "name3": 3,
    "name4": 4
}

注意!!!如果name4行最后有逗号,后面反序列化会出错

然后直接转为Dictionary:

jsonStr = File.ReadAllText(Application.streamingAssetsPath + "/dic.json");
Dictionary<string, int> dic = JsonMapper.ToObject<Dictionary<string, int>>(jsonStr);
  • 文本编码格式需要是UTF-8,不然无法加载

(6)LitJson总结

  • LitJson提供的序列化/反序列化方法:JsonMapper.ToJson和ToObject<>
  • LitJson不用加特性
  • LitJson不支持私有变量
  • LitJson支持字典序列化反序列化
  • LitJson可以直接将数据反序列化为数据集合
  • LitJson反序列化时,自定义类型需要无参构造
  • Json文档编码格式必须是UTF-8

7、JsonUtlity和LitJson对比

(1)相同点:

  • 都是用于Json的序列化和反序列化
  • Json文档编码格式必须时UTF-8
  • 都是通过静态类进行方法调用

(2)不同点:

  • JsonUtility是Unity自带,LitJson是第三方需要引用命名空间
  • JsonUtility使用时自定义类需要添加特性,LitJson不需要
  • JsonUtility支持私有变量(加特性),LitJson不支持
  • JsonUtility不支持字典,LitJson支持(但是键只能是字符串)
  • JsonUtility不能直接将数据反序列化为数据结合(数组字典),LitJson可以
  • JsonUtility对自定义类不要求有无参构造,LitJson需要
  • JsonUtility存储对象时会存储默认值为不是null,LitJson会存null

8、写一个简单的Json管理器

public enum E_JsonType {
    JsonUtility,
    LitJson
}

/// <summary>
/// Json 数据管理,主要用于Json的序列化与反序列化
/// </summary>
public class JsonMgr { 
    private static JsonMgr instance = new JsonMgr();
    public static JsonMgr Instance => instance;

    private JsonMgr() {
        
    }

    public void SaveData(object data, string fileName, E_JsonType type = E_JsonType.LitJson) {
        string path = Application.streamingAssetsPath + "/" + fileName + ".json";
        string jsonStr = "";

        switch (type) {
            case E_JsonType.JsonUtility:
                jsonStr = JsonUtility.ToJson(data);
                break;
            case E_JsonType.LitJson:
                jsonStr = JsonMapper.ToJson(data);
                break;
        }

        File.WriteAllText(path, jsonStr);
    }

    public T LoadData<T>(string fileName, E_JsonType type = E_JsonType.LitJson) where T : new() { 
        string path = Application.streamingAssetsPath + "/" + fileName + ".json";
        if (!File.Exists(path)) 
            path = Application.persistentDataPath + "/" + fileName + ".json";
        
        if (!File.Exists(path)) 
            return new T();
        

        string jsonStr = File.ReadAllText(path);
        T data = default(T);

        switch (type) {
            case E_JsonType.JsonUtility:
                data = JsonUtility.FromJson<T>(jsonStr);
                break;
            case E_JsonType.LitJson:
                data = JsonMapper.ToObject<T>(jsonStr);
                break;
        }

        return data;
    }
}

然后为了方便其他项目使用,可以将其打包,但是要注意,由于使用了LitJson第三方库,所以打包时需要将LitJson源代码一起打包

 然后右键JsonMgr选择Export Package选择对应的文件夹即可生成对应的Package文件

Unity中Newtonsoft.Json的使用(一) Unity中下载Newtonsoft.Json,并进行序列化和反序列化 阅读详情

相关推荐

unity中的数据持久化(PlayerPrefs 使用二进制、XML、JSON来存储读取))

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 数据持久化 前言 提示:这里可以添加本文要记录的大概内容: 在使用unity制作游戏时,经常需要对数据进行存储与读取(例如:角色的属性) 我们刚开始的时候接触的应该是unity提供的PlayerPrefs(通过过key-value的形式写入、读取、更新),在这里记录一下如何使用二进制、XML、JSON来实现 提示:以下是本篇文章正文内容,下面案例可供参考 一、PlayerPrefs PlayerPrefs 是unity的内置的方法,用..

qq_45969040的博客 2213

Unity3D中任意类型数据转换成json数据的方法2

Unity3D中任意类型数据转换成json数据的方法 Posted on 2013年03月20日 by U3d / Unity3D脚本/插件/被围观 275 次

Unity之C#——数据持久化Json

游戏开发中,难免有存档与数据传输需求,在unity中有自带的JsonUtility,也可以使用LitJson。这两这者的用法区别不大,在此我用unity中的JsonUtility演示一下用法。

lijianfex 2091

Unity中的Json序列化及应用

JSON序列化

2503_90324697的博客 1911

Unity——JSON

Json支持的数据结构 数字型:short,int,long,float,double 字符串:“abc”,“你好”,‘abc’ 布尔类型:true,false null:null 数组(列表):[值1,值2] 对象(字典):{"键1":"值1","键2":"值2"} 字符含义 大括号组:对象,字典 中括号组:数组,列表 冒号...

m0_51743362的博客 1万+

UnityJSON

/T:C#接收类型 参数:JSON字符串//加载JSON道具表的TextAsset//获取内部文字//解析JSON//Item表对象下Data成员变量下的第一条数据下的Name成员变量(羊刀)

m0_63330263的博客 3736

Unity_数据持久化_Json

本文介绍了Unity中使用JSON进行数据持久化的方法。主要内容包括:1) JSON基本语法和数据类型,如字符串、数字、布尔值及复杂对象结构;2) Unity内置的JsonUtility工具的使用,包括ToJson序列化和FromJson反序列化方法;3) 实际应用示例,展示了如何将游戏对象转换为JSON格式并存储到文件,以及从文件读取并还原为对象的过程。文中特别强调了JsonUtility对基础类型和自定义类的支持,以及其简单易用、线程安全的特点,为Unity游戏开发中的数据存储和交换提供了高效解决方案。

2503_90324697的博客 1606

Unity——数据持久化Json

本文介绍了JSON文件格式的基础知识及在Unity中的使用方式。主要内容包括:1) JSON基础语法和Excel转JSON的工具介绍;2) Unity内置的JsonUtility使用方法,包括序列化/反序列化操作及注意事项;3) 第三方库LitJson的获取和使用方法,对比分析了其与JsonUtility的优缺点。重点讲解了两种方式在自定义类型、私有变量、字典处理等方面的差异,以及文件读写操作的具体实现方法。

2401_83430690的博客 870

Unity数据持久化操作——Json

本文介绍了JSON文件格式符号含义及在Unity中的使用方法。JSON符号包括{}表示对象、[]表示数组、:表示键值对等。详细讲解了Unity自带的JsonUtility和第三方库LitJson的序列化与反序列化方法,对比了两者的异同点:JsonUtility需要特性标记但支持私有变量,LitJson支持字典但需要无参构造器。最后给出了自定义Json数据管理类的实现方案,封装了存储和读取功能,支持两种序列化方式切换。通过示例代码演示了如何将自定义类对象转换为JSON格式存储到文件,以及如何从文件读取JSON

qq_52796826的博客 1146

Unity学习开发日志-数据持久化Json

~如果感兴趣可以去支持一下b站一唐老狮一

Nan_Gua_pie的博客 786

Unity复习学习笔记(十):Json数据持久化

JSON是一种轻量级数据交换格式,具有易读易写、便于机器解析的特点,广泛应用于网络传输和数据存储。文章对比了JSON与XML的异同,详细介绍了JSON的基本语法、文件格式和编辑方式。重点讲解了UnityJsonUtility和第三方库LitJson的使用方法,包括序列化/反序列化、特性要求、数据集合处理等差异。最后提供了封装Json管理工具类的实践方案,支持多种Json库的灵活切换,为开发者提供了实用的数据存储解决方案。

基本上是拿来做笔记自己看的。 1079

Unity数据持久化保存 ☞ Json方式保存

Unity数据持久化保存 ☞ Json方式保存物体A跟随物体B移动1.子父物体关系2.摄像机跟随物体移动(offset)功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片相机跟随 物体A跟随物体B移动 个人认为所谓的 “ 物体A跟随物体B运动 ” 表现为:二者表现为运动(平移、旋转)方向,速度在任何时刻表现一致。 1.子父物体关系 若想GameObject_A跟随GameObject_B移动,可将GameObject_A的父物体设置为GameObject_B,但是这种方法存在一定的

qq_43511290的博客 982

Unity数据持久化:PlayerPrefs、XML、Json、二进制

PlayerPrefs 是Unity提供的可用于存储游戏数据的公共类。key:string类型。

天行健,君子以自强不息 397

Unity数据持久化——Json

JsonUtility、LitJson、Newtonsoft.Json

weixin_45274937的博客 2113

Unity数据持久化Json

Json是什么?全称:JavaScript对象简谱(JavaScript Object Notation)Json是国际通用的一种轻量级的数据交换格式主要在网络通讯中用于传输数据,或本地数据存储和读取易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率我们一般使用Json文件来记录和传输数据Json文档就是使用Json格式配置填写的文档后缀一般为.json我们在游戏中可以把游戏数据按照Json的格式标准。

K_CRACKING的博客 1702

Unity数据持久化Json 语法速通

Json语法速记

咩咩的博客 678

Unity学习笔记:数据持久化Json(一)基础

Json语法 创建和编辑Json文件 Json注释 Json格式与规范 举例 C#读取存储Json文件 使用JsonUtility 语法 注意事项 使用LitJson 获取LitJson 语法 注意事项 两者对比 相同点 不同点 总结...

游戏开发 1011

Unity游戏数据持久化存储:从PlayerPrefs到JSON序列化的实战指南

数据持久化是软件开发中的基础概念,指将程序运行时的数据状态保存到非易失性存储介质中,使其在程序关闭或设备重启后依然可被读取。其核心原理是通过序列化技术将内存中的对象转换为可存储或传输的格式(如二进制流、文本),再通过文件I/O操作写入磁盘。这项技术的价值在于保障用户体验的连续性和数据可靠性,是游戏存档、应用配置等场景的基石。在Unity开发中,针对不同的数据类型和规模,开发者需在PlayerPrefs、JSON序列化、二进制序列化等方案间做出选择。其中,JSON序列化因其良好的可读性、调试便利性以及与网络传

weixin_29015801的博客 346
上一篇: C# 特殊语法
下一篇: Unity 鼠标操作
Go_Accepted
博客等级 码龄10年 601粉丝 334原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值