使用 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 now contains: '{"level":1,"timeElapsed":47.5,"playerName":"Dr Charles Francis"}'
要将 JSON 转换回对象,请使用 JsonUtility.FromJson:
myObject = JsonUtility.FromJson<MyClass>(json);
这会创建一个新的 MyClass 实例,并使用 JSON 数据设置该实例的值。如果 JSON 数据中包含的某些值未映射到 MyClass 中的字段,那么序列化程序会忽略这些值。如果 JSON 数据缺少 MyClass 中某些字段的值,则序列化程序会在返回的对象中保留这些字段的构造值。
还可以在现有对象上反序列化 JSON 数据,从而覆盖所有现有数据:
JsonUtility.FromJsonOverwrite(json, myObject);
如果 JSON 数据不包含某个字段的值,则序列化程序不会更改该字段的值。此方法可重复使用先前创建的对象,从而将分配工作保持在最低程度。此方法还允许您故意用仅包含一小部分字段的 JSON 来覆盖对象以便“修补”该对象。
警告:JSON 序列化程序的 API 支持 MonoBehaviour 和 ScriptableObject 子类以及普通的结构体和类。但将 JSON 反序列化为 MonoBehaviour 或 ScriptableObject 的子类时,则必须使用 FromJsonOverwrite 方法。如果使用 FromJson,那么 Unity 会抛出异常,因为此行为不受支持。
JSON 序列化程序 API 支持所有 MonoBehaviour 子类、ScriptableObject 子类或拥有 [Serializable] 属性的普通类和结构体。将对象传入到标准 Unity 序列化程序进行处理时,需要遵循的规则和限制与检视面板中相同:Unity 只序列化字段;不支持类似 Dictionary<> 的类型。
Unity 不支持将其他类型直接传给 API,例如原始类型或数组。如果需要转换上述类型,请将它们包裹在某种 class 或 struct 中。
仅在编辑器中存在一个并行 API,即 EditorJsonUtility,可以让您将派生于 UnityEngine.Object 的对象序列化为 JSON,反之亦可。这样生成的 JSON 将包含与对象的 YAML 表示相同的数据。
JsonUtility 和 EditorJsonUtility 都是实用程序类,可用于按 Unity 序列化规则将对象序列化为 JSON 字符串格式(或反之)。如果需要通过代码操作 JSON 数据,或为不支持 Unity 序列化的数据结构进行序列化,可以搭配通用 .NET JSON 库使用 JsonUtility API。
基准测试表明 JsonUtility 显著地快于流行的 .NET JSON 解决方案,尽管此类在某些情况下提供的功能较少。
垃圾收集 (GC) 内存使用量为最低量:
您可以在后台线程中使用 JsonUtility API。但就和任何多线程代码一样,当一个线程正在序列化或反序列化对象时,请勿在另一个线程上访问或更改该对象。
ToJson 支持完美打印 JSON 输出。此功能默认为关闭状态,但可通过传递 true 作为第二个参数来打开此功能。
可以使用 [NonSerialized] 属性在输出中省略字段。
如果事先不知道对象的类型,请将 JSON 反序列化为包含“公共”字段的类或结构,然后使用这些字段的值来判断所需的实际类型。然后第二次反序列化为该类型。