使用 JsonUtility 类可在 Unity 对象与 JSON 格式之间来回转换。例如,可以使用 JSON 序列化与 Web 服务进行交互,或者轻松地将数据压缩和解压缩为基于文本的格式。
JSON 序列化使用“结构化”JSON 的概念:创建一个类或结构来描述将在 JSON 数据中存储的变量。例如:
[Serializable]
public class MyClass
{
public int level;
public float timeElapsed;
public string playerName;
}
此代码段定义了一个包含三个变量(__level、timeElapsed__ 和 __playerName__)的普通 C# 类,并用 Serializable
属性标记该类,这样才能使用 JSON 序列化程序。要创建类的实例,可以使用如下所示的代码:
MyClass myObject = new MyClass();
myObject.level = 1;
myObject.timeElapsed = 47.5f;
myObject.playerName = "Dr Charles Francis";
然后使用 JsonUtility.ToJson 方法将其序列化(转换)为 JSON 格式:
string json = JsonUtility.ToJson(myObject);
// json 现在包含:'{"level":1,"timeElapsed":47.5,"playerName":"Dr Charles Francis"}'
要将 JSON 转换回对象,请使用 JsonUtility.FromJson:
myObject = JsonUtility.FromJson<MyClass>(json);
此代码将创建一个新的 MyClass
实例,并使用 JSON 数据设置该实例的值。如果 JSON 数据包含的某些值未映射到 MyClass
中的字段,则序列化程序将忽略这些值。如果 JSON 数据缺少 MyClass
中某些字段的值,则序列化程序会在返回的对象中保留这些字段的构造值。
JSON 序列化程序当前不支持处理非结构化 JSON。也就是说,不能以任意键值对树的形式浏览和编辑 JSON。如果需要这样做,应采用功能更全面的 JSON 库。
还可以在现有对象上反序列化 JSON 数据,从而覆盖所有现有数据:
JsonUtility.FromJsonOverwrite(json, myObject);
如果 JSON 数据不包含某个字段的值,则序列化程序不会更改该字段的值。此方法可重复使用先前创建的对象,从而可以将分配工作保持在最低限度。此方法还允许您故意用仅包含一小部分字段的 JSON 来覆盖对象以便“修补”对象。
警告:JSON 序列化程序 API 支持 MonoBehaviour 和 ScriptableObject 子类以及普通结构和类。但是,将 JSON 反序列化为 MonoBehaviour
或 ScriptableObject
子类时,必须使用 FromJsonOverwrite 方法。如果尝试使用 FromJson,则 Unity 会抛出异常,因为不支持此行为。
JSON 序列化程序 API 支持任何 MonoBehaviour
子类、ScriptableObject
子类或者带有 [Serializable]
属性的普通类或结构。将对象传入到标准 Unity 序列化程序进行处理时,需要遵循与在 Inspector 中相同的规则和限制:Unity 只序列化字段;不支持类似 Dictionary<>
的类型。
Unity 不支持将其他类型直接传递到 API,例如原始类型或数组。如果需要转换上述类型,则需要将它们包裹在某种 class
或 struct
中。
在 Editor 中且仅在 Editor 中有一个并行 API EditorJsonUtility,允许将 UnityEngine.Object 派生的任何对象与 JSON 进行互相序列化。这样生成的 JSON 将包含与对象的 YAML 表示相同的数据。
基准测试表明,JsonUtility 比流行的 .NET JSON 解决方案要快得多,但此类在某些情况下提供的功能较少。
垃圾收集 (GC) 内存使用量为最低量:
可以使用后台线程中的 JsonUtility API。但是,与任何多线程代码一样,在一个线程上序列化或反序列化对象时,请勿在另一个线程上访问或更改该对象。
ToJson 方法支持完美打印 JSON 输出。此功能默认为关闭状态,但可通过传递 true
作为第二个参数来开启此功能。
可以使用 [NonSerialized]
属性在输出中省略字段。
如果事先不知道对象的类型,请将 JSON 反序列化为包含“公共”字段的类或结构,然后使用这些字段的值来计算出您想要的实际类型。然后第二次反序列化为该类型。