【推荐100个unity插件之37】unity使用三种方式实现对Json数据的序列化和反序列化持久化存储,并举例分析JsonUtlity、LitJSON和Newtonsoft的区别

前言

unity对Json数据的序列化和反序列化其实之前已经做过很多了,但是都是零零散散,并没有进行系统的整理,这次我特地单独拿出来讲讲。

传送门:
【unity框架开发12】从零手搓unity存档存储数据持久化系统,实现对存档的创建,获取,保存,加载,删除,缓存,加密,支持多存档(2024/11/23补充)

【推荐100个unity插件之20】一个强大的JSON处理库——Newtonsoft.Json(也称为Json.NET)

【unity框架开发12】从零手搓unity存档存储数据持久化系统,实现对存档的创建,获取,保存,加载,删除,缓存,加密,支持多存档(2024/11/23补充)

一、前置知识

1、获取各种文件路径

Application.persistentDataPath获取的是一个持久化的数据路径,在不同的操作系统上,unity会为我们分配不同的持久化数据路径,这样可以确保应用程序在不同平台上都能正确保存和访问

//设置存档文件路径
savePath = Path.Combine(Application.persistentDataPath, "saveData.json");

不同平台存储的路径不一样,我们可以打印savePath查看自己的存储路径

比如我PC上的就是
在这里插入图片描述

其他:https://blog.csdn.net/qq_36303853/article/details/129688513

2、将字符串存入文件中

File.WriteAllText()将字符串写入到指定路径文件中

  • 第一个参数填写的是存储的路径
  • 第二个参数填写的是存储的字符串内容
  • 注意:第一个参数必须是存在的文件路径如果没有对应文件夹会报错
File.WriteAllText(Application.persistentDataPath + "/Test.json", "json文件");

3、读取文件中的字符串内容

string str = File.ReadAllText(Application.persistentDataPath + "/Test.json");

4、什么是序列化和反序列化

  • 序列化其实就是把内存中的数据存储到硬盘上
  • 反序列化其实就是把硬盘上的数据读取到内存中

二、JsonUtlity

1、JsonUtlity是什么?

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

  • 将内存中对象序列化为Json格式的字符串
  • 将Json字符串反序列化为类对象

2、注意

  • float序列化时看起来会有一些误差,但是读取其实不影响
  • 自定义类需要加上序列化特性[System.Serializable]
  • 想要序列化私有变量需要加上特性[SerializeField]
  • JsonUtlity可以序列化vector Color Quaternion等数据
  • JsonUtlity不支持字典
  • JsonUtlity存储null数据不会是null,而是默认值,比如string就会是空字符""

3、实例

定义一些不同类型的数据

public class Data{
    public string name = "小明";
    public string name2 = null;
    public int age = 12;
    public float height = 1.85f;
    public int[] ids = {1, 2, 3};
    public List<int> list = new List<int>{11, 22, 33};
    public Dictionary<int, string> intDic = new Dictionary<int, string>{{1, "内容1"}, {2, "内容2"}, {3, "内容3"}};
    public Dictionary<string, string> strDic = new Dictionary<string, string>{{"key1", "内容1"}, {"key2", "内容2"}, {"key3", "内容3"}};
    public Son son2 = new Son("子数据", 1);
    public List<Son> listSon = new List<Son>{new Son("数据1", 1), new Son("子数据2", 2)};
    public Vector3 vector3 = new Vector3(1, 2, 1);
    public Color color = Color.red;
    public Quaternion rotation = Quaternion.Euler(0f, 90f, 0f);
    [SerializeField]
    private int privateInt = 66;
    [SerializeField]
    protected int protectedInt = 77;

    public override string ToString()
    {
        string result = $"Name: {name}, Name2: {name2}, Age: {age}, Height: {height}, " +
                        $"IDs: {string.Join(", ", ids)}, List: {string.Join(", ", list)}\n" +
                        $"IntDic: {string.Join(", ", intDic)}, StrDic: {string.Join(", ", strDic)}\n" +
                        $"Son2: {son2}, ListSon: {string.Join(", ", listSon)}\n" +
                        $"vector3: {vector3}, color: {color}, rotation: {rotation}\n" +
                        $"privateInt: {privateInt}, protectedInt: {protectedInt}";
        return result;
    }
}

[System.Serializable]
public class Son{
    public string name;
    public int age;

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

使用JsonUtility.ToJson进行序列化

Data data = new Data();
string jsonData = JsonUtility.ToJson(data);
File.WriteAllText(Application.persistentDataPath + "/Test.json", jsonData);

存储结果

可以看到如前面所说,字典无法存储,float类型存储有些误差,null数据存储的是默认值
在这里插入图片描述

使用JsonUtlity进行反序列化

string jsonStr = File.ReadAllText(Application.persistentDataPath + "/Test.json");
Data data2 = JsonUtility.FromJson<Data>(jsonStr);
print(data2.ToString());

打印结果,这里还是有打印出字典的原因是因为,字典数据没有读取到,所以输出了默认值
在这里插入图片描述

4、JsonUtility不能直接将数据反序列化为数据集合

比如我们想读取这样的数组json数据
在这里插入图片描述
定义数据

public class Data1
{
    public string name;
    public int age;
    
    public override string ToString()
    {
        string result = $"name: {name}, age: {age}";
        return result;
    }
}

读取

string jsonStr = File.ReadAllText(Application.persistentDataPath + "/Test.json");
List<Data1> data2 = JsonUtility.FromJson<List<Data1>>(jsonStr);
print(data2[0].ToString());

结果直接会报错
在这里插入图片描述

5、总结

  • File存读字符串的方法ReadAllText和WriteAllText
  • JsonUtility提供的序列化反序列化方法ToJson和FromJson
  • 自定义类需要加上序列化特性[System.Serializable]
  • 想要序列化私有变量需要加上特性[SerializeField]
  • JsonUtility不支持字典
  • JsonUtility不能直接将数据反序列化为数据集合
  • Json文档编码格式必须是UTF-8

三、LitJSON

1、什么是LitJSON?

它是一个第三方库,用于处理Jso的序列化和反序列化,LitJson是c#编写的,体积小、速度快、易于使用,它可以很容易的嵌入到我们的代码中,只需要将LitJson代码拷贝到工程中即可

2、获取LitJson

官网

https://litjson.net/

GitHub

https://github.com/LitJSON/litjson
在这里插入图片描述
导入LitJson进项目
在这里插入图片描述

留代码即可
在这里插入图片描述

3、注意

  • 相对于JsonUtility不需要加特性
  • 不能序列化私有变量
  • 支持字典类型,字典的键建议都是字符串因为Json的特点Json中的键会加上双引号
  • 需要导入LitJson和引用LitJson命名空间
  • LitJson可以准确的保存null类型
  • LitJson无法序列化vector Color Quaternion等数据
  • 类结构需要无参构造函数,否则反序列化时报错
  • 字典虽然支持,但是键为数值反序列化时会有问题,所以字典的键需要严格使用字符串类型才对

4、案例

定义一些不同类型的数据

public class Data{
    public string name = "小明";
    public string name2 = null;
    public int age = 12;
    public float height = 1.85f;
    public int[] ids = {1, 2, 3};
    public List<int> list = new List<int>{11, 22, 33};
    public Dictionary<string, string> strDic = new Dictionary<string, string>{{"key1", "内容1"}, {"key2", "内容2"}, {"key3", "内容3"}};
    public Son son2 = new Son("子数据", 1);
    public List<Son> listSon = new List<Son>{new Son("数据1", 1), new Son("子数据2", 2)};
	
	public override string ToString()
    {
        string result = $"Name: {name}, Name2: {name2}, Age: {age}, Height: {height}, " +
                        $"IDs: {string.Join(", ", ids)}, List: {string.Join(", ", list)}\n" +
                        $"StrDic: {string.Join(", ", strDic)}\n" +
                        $"Son2: {son2}, ListSon: {string.Join(", ", listSon)}\n";
        return result;
    }
}

public class Son{
    public string name;
    public int age;
	
	//注意不能省略,下面会说原因
	public Son() { }
	
    public Son(string name, int age){
        this.name = name;
        this.age = age;
    }
}

使用LitJson序列化

Data data = new Data();
string jsonData = JsonMapper.ToJson(data);
File.WriteAllText(Application.persistentDataPath + "/Test.json", jsonData);

存储结果
在这里插入图片描述

使用LitJson进行反序列化

string jsonStr = File.ReadAllText(Application.persistentDataPath + "/Test.json");
Data data2 = JsonMapper.ToObject<Data>(jsonStr);
print(data2.ToString());

打印结果
在这里插入图片描述

再次强调

  • 类结构需要无参构造函数,否则反序列化时报错,也就是我前面public Son() { }不能省略的原因
  • 字典虽然支持,但是键为数值反序列化时会有问题,所以字典的键需要严格使用字符串类型才对

5、LitJson能直接将数据反序列化为数据集合

比如我们想读取这样的数组json数据
在这里插入图片描述
定义数据

public class Data1
{
    public string name;
    public int age;
    
    public override string ToString()
    {
        string result = $"name: {name}, age: {age}";
        return result;
    }
}

读取

string jsonStr = File.ReadAllText(Application.persistentDataPath + "/Test.json");
List<Data1> data2 = JsonMapper.ToObject<List<Data1>>(jsonStr);
print(data2[0].ToString());

结果
在这里插入图片描述

6、总结

  • LitJson提供的序列化反序列化方法JsonMapper.ToJsonJsonMapper.ToObject<>
  • LitJson无需加特性
  • LitJson不支持私有变量
  • LitJson支持字典序列化反序列化
  • 字典虽然支持,但是键为数值反序列化时会有问题,所以字典的键需要严格使用字符串类型才对
  • LitJson可以直接将数据反序列化为数据集合
  • LitJson反序列化时自定义类型需要无参构造
  • Json文档编码格式必须是UTF-8
  • 使用LitJson需要导入LitJson和引用LitJson命名空间
  • LitJson可以准确的保存null类型
  • LitJson无法序列化vector Color Quaternion等数据

四、Newtonsoft

1、什么是Newtonsoft?

Newtonsoft.Json 是一个非常流行的 C# JSON 序列化和反序列化库,它可以方便地将 C# 对象转换为 JSON 格式,或者将 JSON 数据解析为 C# 对象。

相比其他的JSON工具,Newtonsoft.Json支持绝大多数平台。有着最丰富的功能和API,不夸张的说,可以支持所有的数据结构类型,包括你自定义的数据结构类型,且序列化反序列化过程可定制。

与之相对的,Newtonsoft.Json的包体也会稍大,如果对包体的大小不追求极限的话,可以说Newtonsoft.Json就是你在Unity开发中使用Json的不二之选。

2、获取Newtonsoft

直接在unity安装插件支持即可
在这里插入图片描述
如果安装了还是无法使用,记得重启unity再试即可

3、注意

  • 使用Newtonsoft需要引入Newtonsoft.Json命名空间
  • Newtonsoft无需加特性
  • Newtonsoft不支持私有变量
  • Newtonsoft支持键为数值或者字符串的字典序列化反序列化
  • Newtonsoft可以直接将数据反序列化为数据集合
  • Newtonsoft可以准确的保存null类型
  • Newtonsoft可以序列化vector Color Quaternion等数据,不过需要额外配JsonSerializerSettings参数

4、案例

定义一些不同类型的数据

public class Data
{
    public string name = "小明";
    public string name2 = null;
    public int age = 12;
    public float height = 1.85f;
    public int[] ids = { 1, 2, 3 };
    public List<int> list = new List<int> { 11, 22, 33 };
    public Dictionary<int, string> intDic = new Dictionary<int, string> { { 1, "内容1" }, { 2, "内容2" }, { 3, "内容3" } };
    public Dictionary<string, string> strDic = new Dictionary<string, string> { { "key1", "内容1" }, { "key2", "内容2" }, { "key3", "内容3" } };
    public Son son2 = new Son("子数据", 1);
    public List<Son> listSon = new List<Son> { new Son("数据1", 1), new Son("子数据2", 2) };
    public Vector3 vector3 = new Vector3(1, 2, 1);
    public Color color = Color.red;
    public Quaternion rotation = Quaternion.Euler(0f, 90f, 0f);

    public override string ToString()
    {
        string result = $"Name: {name}, Name2: {name2}, Age: {age}, Height: {height}, " +
                        $"IDs: {string.Join(", ", ids)}, List: {string.Join(", ", list)}\n" +
                        $"IntDic: {string.Join(", ", intDic)}, StrDic: {string.Join(", ", strDic)}\n" +
                        $"Son2: {son2}, ListSon: {string.Join(", ", listSon)}\n"+
                        $"vector3: {vector3}, color: {color}, rotation: {rotation}";
        return result;
    }
}

public class Son
{
    public string name;
    public int age;

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

使用Newtonsoft序列化

Data data = new Data();
var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto,
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    Formatting = Formatting.Indented,
};
string jsonData = JsonConvert.SerializeObject(data, settings);
File.WriteAllText(Application.persistentDataPath + "/Test.json", jsonData);

JsonSerializerSettings 对象介绍

TypeNameHandling = TypeNameHandling.Auto:

  • 这个设置告诉 JSON 序列化器在序列化对象时,自动将类型信息包含在 JSON 数据中。这样,当你反序列化该 JSON 字符串时,可以恢复对象的确切类型。
  • Auto 选项表示只会在对象中包含具体类型信息,如果遇到继承自某个基类的类型时,会自动添加基类的类型信息。其他选项还包括 None(不包括类型信息)和 All(包括所有类型信息)。

ReferenceLoopHandling = ReferenceLoopHandling.Ignore:

  • 这个设置指定在序列化时遇到引用循环(例如,一个对象的属性又引用了自己或其父对象时)应该如何处理。设置为 Ignore 时,序列化器会跳过这些循环引用。
  • 这种情况通常出现在包含互相引用的复杂对象结构中,比如两个对象相互引用对方。

Formatting = Formatting.Indented:

  • 设置序列化的 JSON 字符串格式。Indented 会让输出的 JSON 格式化成易读的缩进格式(即,每层嵌套都会有缩进)。这在调试时非常有用,因为它使得 JSON 内容更加清晰。

结果,因为前面设置了Formatting = Formatting.Indented,存储的内容格式就是这样,我并没有进行美化
在这里插入图片描述

使用Newtonsoft进行反序列化

var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto,
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    Formatting = Formatting.Indented,
};
string jsonStr = File.ReadAllText(Application.persistentDataPath + "/Test.json");
Data data2 = JsonConvert.DeserializeObject<Data>(jsonStr, settings);
print(data2.ToString());

打印结果
在这里插入图片描述

5、Newtonsoft能直接将数据反序列化为数据集合

比如我们想读取这样的数组json数据
在这里插入图片描述
定义数据

public class Data1
{
    public string name;
    public int age;
    
    public override string ToString()
    {
        string result = $"name: {name}, age: {age}";
        return result;
    }
}

读取

string jsonStr = File.ReadAllText(Application.persistentDataPath + "/Test.json");
List<Data1> data2 = JsonConvert.DeserializeObject<List<Data1>>(jsonStr);
print(data2[0].ToString());

结果
在这里插入图片描述

6、总结

  • Newtonsoft提供的序列化反序列化方法JsonConvert.SerializeObjectJsonConvert.DeserializeObject<>
  • 使用Newtonsoft需要引入Newtonsoft.Json命名空间
  • Newtonsoft无需加特性
  • Newtonsoft不支持私有变量
  • Newtonsoft支持键为数值或者字符串的字典序列化反序列化
  • Newtonsoft可以直接将数据反序列化为数据集合
  • Json文档编码格式必须是UTF-8
  • Newtonsoft可以准确的保存null类型
  • Newtonsoft可以序列化vector Color Quaternion等数据,不过需要额外配JsonSerializerSettings参数
  • Newtonsoft还可以对Json格式美化,存储成易读的缩进格式

五、结论

结论毋庸置疑了,Newtonsoft集合了JsonUtlity和LitJSON的所有优点,又巧妙避开了所有缺点,而且它还有自己的优点,比如对Json格式美化。如果一定要说缺点的话,那可能就是Newtonsoft的包体比JsonUtlity和LitJSON大一点,不过也仅仅是大一点而已。

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,闲暇之余,边学习边记录分享,站在巨人的肩膀上,通过学习前辈们的经验总是会给我很多帮助和启发!如果你遇到任何问题,也欢迎你评论私信或者加群找我, 虽然有些问题我也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向宇it

创作不易,感谢你的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值