unity数据持久化-json
JsonUtlity
JsonUtlity是unity自带的序列化和反序列化工具类,主要提供了两个方法ToJson 和FromJson
ToJson序列化
比如我们有一个类是这样的
class Person1
{
public int testI;
public float testF;
public double testD;
public string testS;
public int[] testArr;
public List<int> testList;
public Dictionary<int, string> testDic;
public Person2 testObj;
private int testPri = 1;
}
class Person2
{
public string name;
public int age;
}
其中包括大部分常用的数据类型,我们可以通过JsonUtlity提供的ToJson Api来实现序列化
Person1 p = new Person1();
p.testI = 18;
p.testF = 1.22f;
p.testD = 1.22;
p.testS = "XXX";
p.testArr = new[] { 1, 2, 3 };
p.testList = new List<int>() { 1, 2, 3 };
p.testDic = new Dictionary<int, string>() { { 1, "test" } };
p.testObj = new Person2() { name = "xxx", age = 18 };
print(JsonUtility.ToJson(p));
//out:
{"testI":18,"testF":1.2200000286102296,"testD":1.22,"testS":"XXX","testArr":[1,2,3],"testList":[1,2,3]}
结果中没有包含
- 私有的成员
- dictionary类型
- 自定义class
在System名称空间中提供了两个特性
[Serializable] //用于标识序列化class
[SerializeField] //用于标识序列化成员
为上述两个类补充上这序列化的特性
[Serializable]
class Person2{
...
}
Class Person1{
...
[Serializable]
private int testPri = 1;
}
再次运行发现除了Dictionary类型之外都能为序列化
FromJson反序列化
通过序列化得到的json字符串
{"testI":18,"testF":1.2200000286102296,"testD":1.22,"testS":"XXX","testArr":[1,2,3],"testList":[1,2,3],"testObj":{"name":"xxx","age":18},"testPri":1}
可以通过
JsonUtility.FromJson<Type>(jsonStr);
来反序列化
{"testI":18,"testF":1.2200000286102296,"testD":1.22,"testS":"XXX","testArr":[1,2,3],"testList":[1,2,3],"testObj":{"name":"xxx","age":18},"testPri":1}
JsonUtlity序列化的不足
无法序列化Dictionary类型
未赋值的成员变量会使用对应的默认值
Person1 p = new Person1();
string jsonStr = JsonUtility.ToJson(p);
print(jsonStr);
//out:
{"testI":0,"testF":0.0,"testD":0.0,"testS":"","testArr":[],"testList":[],"testObj":{"name":"","age":0},"testPri":1}
可以看到,我们在没有对p进行赋值的情况下,它的所有能被序列化的成员都使用了各自的默认值
无法直接读取数据集合
比如我们有一段json格式字符串
[
{"hp":10,"attack":5},
{"hp":20,"attack":5},
{"hp":30,"attack":5}
]
数组的每一个元素为一个对象
class GameObj{
public int hp;
public int attack;
}
使用FromJson反序列化的时候会报错
string jsonStr =
"[\n {\"hp\":10,\"attack\":5},\n {\"hp\":20,\"attack\":5},\n {\"hp\":30,\"attack\":5}\n]";
GameObj[] arr = JsonUtility.FromJson<GameObj[]>(jsonStr);
print(arr);
//ArgumentException: Return type must represent an object type. Received an array.
总结
- JsonUtlity提供的序列化反序列化方法 ToJson 和 FromJson
- 自定义类需要加上序列化特性[System.Serializable]
- 私有保护成员 需要加上[SerializeField]
- JsonUtlity不支持字典
- JsonUtlity不能直接将数据反序列化为数据集合
LitJson
LitJson和JsonUtlity一样属于第三方json序列化工具
获取litJson
github: GitHub - LitJSON/litjson: JSON library for the .Net framework
下载之后解压将下面文件夹拖入unity中
使用litjson序列化
api:
JsonMapper.ToJson(obj)
准备一个测试序列化的类
class Test
{
public int testI;
public float testF;
public string testS;
public List<int> testList;
public Dictionary<string, string> testDic;
public Person testP;
private int testPri = 1;
}
new一个对象并给所有成员变量赋值
Test t = new Test();
t.testI = 1;
t.testF = 1.2f;
t.testS = "hello";
t.testList = new List<int>() { 1, 2, 3, 4 };
t.testDic = new Dictionary<string, string>() { {"1","name"} };
t.testP = new Person();
print(JsonMapper.ToJson(t));
//out:
{"testI":1,"testF":1.2,"testS":"hello","testList":[1,2,3,4],"testDic":{"1":"name"},"testP":{"name":null,"age":0}}
和JsonUtlity不同是的,LitJson不用给Person 类添加特性使其可以被序列化,字典类型可以正常的被序列化,但是私有字段无法被支持
除此之外,如果我们不给 t.testP 赋值
那么序列化出来的结果
t.testP 赋值
//out
{"testI":1,"testF":1.2,"testS":"hello","testList":[1,2,3,4],"testDic":{"1":"name"},"testP":null}
那么testP 的结果便为null,而JsonUtlity则会生成一个多有成员都是默认值的对象
LitJson反序列化
api :
JsonMapper.ToObject<Test>(jsonStr)
使用序列化的json字符串进行反序列化
{"testI":1,"testF":1.2,"testS":"hello","testList":[1,2,3,4],"testDic":{"1":"name"},"testP":{"name":null,"age":0}}
注意
类成员中自定义的class对象需要无参构造函数,否则反序列化会报错
字典只能是string类型作为键
可以直接序列化集合类型
总结
- LitJson提供的序列化反序列化方法 JsonMapper.ToJson和ToObject<>
- LitJson无需加特性
- LitJson不支持私有变量
- LitJson支持字典序列化反序列化
- LitJson可以直接将数据反序列化为数据集合
- LitJson反序列化时 自定义类型需要无参构造
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!