版本:2022.3
语言:英语
脚本序列化错误
脚本编译

JSON序列化

使用JsonUtility类将Unity对象转换为JSON格式,并将JSON格式转换回Unity对象。例如,您可以使用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的子类,以及具有[Serializable]属性的普通结构或类。但是,当将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是实用程序类,用于将对象序列化到JSON字符串格式以及从JSON字符串反序列化对象,使用的是Unity序列化规则。在需要通过代码操纵JSON数据或序列化Unity的序列化器不支持的数据结构的情况下,您可以使用通用的.NET JSON库作为JsonUtility API的配套工具。

性能

基准测试表明,尽管在某些情况下这个类提供的功能更少,但JsonUtility 的速度明显快于流行的 .NET JSON解决方案。

垃圾收集(GC)的内存使用量达到最小值。

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

您可以在后台线程中调用 JsonUtility API。然而,与任何多线程代码一样,请小心不要在一个线程上访问或修改对象,同时另一个线程正在将其序列化或反序列化。

控制 ToJson() 的输出

ToJson 方法支持漂亮的 JSON 输出。默认情况下是关闭的,但您可以通过将 true 作为第二个参数来打开。

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

使用 FromJson() 与未知类型

如果您事先不知道对象的类型,可以将 JSON 反序列化到一个包含“常用”字段的类或结构体,然后使用这些字段的值来确定您需要的实际类型。然后再次将 JSON 反序列化到该类型。

脚本序列化错误
脚本编译