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