版本:Unity 6 (6000.0)
语言:英语
Unity 如何使用序列化
脚本序列化错误

JSON 序列化

使用 JsonUtility 类将 Unity 对象转换为 JSON 格式,反之亦然。例如,您可以使用 JSON 序列化与 Web 服务交互,或轻松地将数据打包和解包到文本格式。

JSON 序列化使用“结构化” JSON 的概念:您创建类或结构来描述您想在 JSON 数据中存储的变量。例如

[Serializable]
public class MyClass
{
    public int level;
    public float timeElapsed;
    public string playerName;
}

这定义了一个包含三个变量(leveltimeElapsedplayerName)的普通 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 覆盖对象

您还可以将 JSON 数据反序列化到现有对象,这将覆盖所有现有数据

JsonUtility.FromJsonOverwrite(json, myObject);

如果 JSON 数据不包含字段的值,则序列化器不会更改该字段的值。此方法允许您通过重复使用以前创建的对象来最大程度地减少分配。它还允许您通过有目的地用仅包含一小部分字段的 JSON 来覆盖对象,从而“修补”对象。

警告:JSON 序列化器 API 支持 MonoBehaviourScriptableObject 子类,以及普通结构和类。但是,当将 JSON 反序列化到 MonoBehaviourScriptableObject 的子类时,您必须使用 FromJsonOverwrite 方法。如果您尝试使用 FromJson,Unity 会抛出异常,因为此行为不受支持。

支持的类型

JSON 序列化器 API 支持任何 MonoBehaviour 子类、ScriptableObject 子类或带有 [Serializable] 属性的普通类或结构。当您将对象传递到标准 Unity 序列化器以进行处理时,与 Inspector 中的规则和限制相同:Unity 仅序列化字段;并且不支持 Dictionary<> 之类的类型。

Unity 不支持将其他类型直接传递到 API,例如原始类型或数组。如果需要转换它们,请将它们包装在某种 classstruct 中。

仅在编辑器中,有一个并行的 API,EditorJsonUtility,它允许您将从 UnityEngine.Object 派生的任何对象序列化到 JSON 中,反之亦然。这会生成与对象的 YAML 表示形式包含相同数据的 JSON。

JsonUtilityEditorJsonUtility 是用于使用 Unity 序列化规则 将对象序列化到 JSON 的字符串格式,反之亦然的实用程序类。在需要通过代码操作 JSON 数据或序列化 Unity 序列化不支持的数据结构的情况下,您可以使用通用的 .NET JSON 库作为 JsonUtility API 的补充。

性能

基准测试表明,JsonUtility 比流行的 .NET JSON 解决方案快得多,即使此类在某些情况下提供的功能更少。

用于垃圾收集 (GC) 的内存使用量降至最低

  • ToJson 仅为返回的字符串分配 GC 内存。
  • FromJson 仅为返回的对象分配 GC 内存,以及任何所需的子对象(例如,如果您反序列化包含数组的对象,则 Unity 会为数组分配 GC 内存)。
  • FromJsonOverwrite 仅在需要为写入的字段分配 GC 内存(例如,字符串和数组)。这意味着如果所有被 JSON 覆盖的字段都是值类型,则 Unity 根本不会分配任何 GC 内存。

您可以从后台线程使用 JsonUtility API。但是,与任何多线程代码一样,请注意不要在另一个线程正在序列化或反序列化对象时访问或更改该对象。

控制 ToJson() 的输出

ToJson 方法支持对 JSON 输出进行美化打印。默认情况下它处于关闭状态,但您可以通过将 true 作为第二个参数传递来打开它。

您可以使用 [NonSerialized] 属性省略输出中的字段。

使用 FromJson() 处理未知类型

如果您事先不知道对象的类型,请将 JSON 反序列化到包含“通用”字段的类或结构中,然后使用这些字段的值来确定您想要的实际类型。然后,第二次反序列化到该类型。

Unity 如何使用序列化
脚本序列化错误