Unity中JsonUtility序列化泛型类列表SceneProperties失败如何解决
问题根源
Unity自带的JsonUtility序列化有两个核心限制,导致你的SceneProperties列表无法被正常序列化:
- 不支持默认的多态序列化:你声明的列表类型是抽象基类
SceneProperty,JsonUtility序列化时只会识别字段声明的类型,完全忽略运行时存入的SceneProperty<int>、SceneProperty<bool>等泛型派生类型,遇到抽象类类型的字段会直接跳过序列化。 - 原代码存在隐性bug:
SceneProperties列表没有在类里初始化,new SceneComponent()后该字段为null,JsonUtility遇到null值的集合字段不会输出任何内容,你调用Add方法时本身就会触发空引用异常。
可行解决方案
根据你使用的Unity版本,选以下方案即可:
方案1:使用[SerializeReference]特性(推荐,Unity 2019.3及以上版本可用)
Unity 2019.3新增的[SerializeReference]特性专门用于支持引用类型的多态序列化,加上后JsonUtility会自动记录存入列表的实际对象类型,正确序列化闭合泛型派生类的字段,改动量最小。
修改后的代码如下:
[System.Serializable] public class SceneComponent { public string ComponentType; public string AssemblyName; public int ComponentID; // 加特性启用多态引用序列化,同时初始化列表避免空引用 [SerializeReference] public List<SceneProperty> SceneProperties = new List<SceneProperty>(); }
抽象基类和泛型派生类不需要改动,保持原有写法即可,序列化时会自动带上类型信息,反序列化也能正确还原为对应泛型类型的实例。
方案2:非泛型兼容写法(支持所有Unity版本)
如果你的项目Unity版本低于2019.3,无法使用[SerializeReference],可以放弃泛型多态结构,直接在非泛型的SceneProperty类中定义所有需要支持的属性类型字段,配合你已经存的PropertyType字段区分类型,兼容性最好。
代码示例:
[System.Serializable] public class SceneProperty { public string PropertyPath; public string PropertyType; // 按需添加你需要序列化的所有值类型字段 public int IntValue; public bool BoolValue; public float FloatValue; public string StringValue; public Vector3 Vector3Value; }
赋值时根据属性类型给对应字段赋值即可:
SceneComponent sc = new SceneComponent(); // 其他字段赋值逻辑 // 存int属性 sc.SceneProperties.Add(new SceneProperty{ PropertyPath = property.propertyPath, PropertyType = property.propertyType.ToString(), IntValue = property.intValue }); // 存bool属性 sc.SceneProperties.Add(new SceneProperty{ PropertyPath = property.propertyPath, PropertyType = property.propertyType.ToString(), BoolValue = property.boolValue });
这种写法JsonUtility可以100%正常序列化,没有任何兼容问题,只是需要手动维护支持的类型字段。
方案3:替换序列化库
如果不想改动原有数据结构,可以直接换用支持多态、泛型序列化的第三方库(比如Newtonsoft.Json),不需要给类加额外特性就能正确序列化泛型列表,不过会放弃JsonUtility的性能优势。
内容的提问来源于stack exchange,提问作者Mossi
相关产品推荐
相关产品推荐

