Unity Json 数据持久化
1.序列化和反序列化的两种方案JsonUtility(Unity内置 不推荐)、LitJson(需要导入第三方代码文件 推荐使用)
| 特性 |
JsonUtility(Unity 内置) |
LitJson(第三方推荐) |
| 字典支持 |
❌ 不支持字典 |
✅ 支持字典(键必须是 string) |
| null 值支持 |
❌ 对象 null 会变成默认值 |
✅ 支持 null |
| 集合最外层 |
必须是对象 {} |
可以是数组 [] |
| 私有变量支持 |
✅ [SerializeField] |
❌ 不支持私有变量 |
| 自定义类特性 |
✅ [System.Serializable] |
❌ 不需要特性,但类必须有无参构造函数 |
使用JsonUtility和LitJson时,数据结构区别
//JsonUtility 必须定义PlayerData,PlayerData里面声明playerList列表
//PlayerData和PlayerInfo是自定义类,JsonUtility必须使用[System.Serializable]
[System.Serializable]
public class PlayerData
{
public List<PlayerInfo> playerList; // 集合必须放在对象里
}
[System.Serializable]
public class PlayerInfo
{
public string playerName;
public int level;
}
//LitJson 有两种方式
//第一种 和JsonUtility一样 定义类包裹玩家信息集合(不推荐)
public class PlayerData
{
public List<PlayerInfo> playerList; // 集合必须放在对象里
}
public class PlayerInfo
{
public string playerName;
public int level;
}
//第二种 直接定义玩家信息(推荐 Excel转Json 就是这种数据格式)
public class PlayerInfo
{
public string playerName;
public int level;
}
使用JsonUtility和LitJson时,配置文件格式\导出文件格式区别(配置文件使用Excel转Json 不用手动编写Json)
//JsonUtility只有一种格式
//以类的格式读取数据(没有定义PlayerData类就不能够使用)
{
"playerList":
[
{"playerName": "Alice", "level": 5},
{"playerName": "Bob", "level": 10},
{"playerName": "Charlie", "level": 8}
]
}
//LitJson 有两种格式
//第一种,以类的格式读取数据(没有定义PlayerData类就不能够使用)
{
"playerList":
[
{ "playerName": "Alice", "level": 5 },
{ "playerName": "Bob", "level": 10 },
{ "playerName": "Charlie", "level": 8 }
]
}
//第二种,省略列表类,自定义列表格式读取数据(无论是否定义PlayerData类都可以使用 需要自己定义List<PlayerInfo> playerList接收)
[
{ "playerName": "Alice", "level": 5 },
{ "playerName": "Bob", "level": 10 },
{ "playerName": "Charlie", "level": 8 }
]
使用JsonUtility和LitJson时,反序列化数据的区别
// JsonUtility只有一种反序列化数据的方式
//只能以对象形式读取数据
PlayerData playerData = JsonDataMgr.Instance.Load<PlayerData>("PlayerData");
//LitJson有两种反序列化数据的方式
//第一种 以对象形式读取数据(不推荐)
PlayerData playerData = JsonDataMgr.Instance.Load<PlayerData>("PlayerData");
//第二种 以自定义列表格式读取数据(推荐 Excel转Json 就是这种数据格式)
List<PlayerInfo> playerList = JsonDataMgr.Instance.Load<List<PlayerInfo>>("PlayerData");
2. 通用的 Json 管理器:JsonDataMgr(支持序列化、反序列字典数据)
using LitJson;
using System;
using System.IO;
using UnityEngine;
/// <summary>
/// 序列化和反序列化json时 使用的是哪种方案
/// </summary>
public enum JsonType
{
JsonUtility,
LitJson,
}
/// <summary>
/// Json数据管理 主要用于 Json的序列化到硬盘 和 反序列化从硬盘读取到内存中
/// </summary>
public class JsonDataMgr
{
private static JsonDataMgr instance = new JsonDataMgr();
public static JsonDataMgr Instance => instance;
private JsonDataMgr() { }
public void SaveData(object data,string fileName,JsonType type=JsonType.LitJson)
{
//确定存储路径
string path = Application.persistentDataPath + "/" + fileName + ".json";
//序列化得到json字符串
string jsonStr = "";
switch (type)
{
case JsonType.JsonUtility:
jsonStr = JsonUtility.ToJson(data);
break;
case JsonType.LitJson:
jsonStr = JsonMapper.ToJson(data);
break;
}
//把序列化的json字符串 存储到指定路径的文件中
File.WriteAllText(path, jsonStr);
}
public T LoadData<T>(string fileName, JsonType type = JsonType.LitJson) where T : new()
{
//确定读取的路径
//首先判断 读写数据文件夹中是否有我们想要的资源 如果有 就从中获取
string path = Application.persistentDataPath + "/" + fileName + ".json";
//如果不存在读写数据文件资源 就从默认数据文件夹中获取
if (!File.Exists(path))
{
path = Application.streamingAssetsPath + "/" + fileName + ".json";
}
//如果默认文件夹中还没有 返回默认值
if(!File.Exists(path))
{
Console.WriteLine("不存在文件资源");
//返回默认值 因为传进来的也是默认值 保持输入输出不变
return new T();
}
string jsonStr = File.ReadAllText(path);
T data = default(T);
switch (type)
{
case JsonType.JsonUtility:
data = JsonUtility.FromJson<T>(jsonStr);
break;
case JsonType.LitJson:
data = JsonMapper.ToObject<T>(jsonStr);
break;
}
return data;
}
}
3.LitJson字典的配置文件格式(字典格式:必须手动编写 JSON 配置文件 所以配置文件不推荐使用字典)
//数据结构
public class PlayerData
{
// 使用字典保存玩家信息,键是玩家名字,值是 PlayerInfo
public Dictionary<string, PlayerInfo> playerDict = new Dictionary<string, PlayerInfo>();
}
public class PlayerInfo
{
public string playerName;
public int level;
}
//配置文件格式
{
"Alice": { "playerName": "Alice", "level": 5 },
"Bob": { "playerName": "Bob", "level": 10 },
"Charlie": { "playerName": "Charlie", "level": 8 }
}
4.Excel转Json(不用自己手动编写Json配置文件)
id name state isNew
1 天下无双1 0 false
2 天下无双2 1 false
3 天下无双3 2 false
[
{"id":1,"name":"天下无双1","state":0,"isNew":false},
{"id":2,"name":"天下无双2","state":1,"isNew":false},
{"id":3,"name":"天下无双3","state":2,"isNew":false}
]