Unity中Newtonsoft.Json反序列化继承类型报错的排查与解决
问题分析与解决方案
问题原因
这个报错确实和Newtonsoft.Json对继承类型的默认处理逻辑有关。默认情况下,JSON.NET不会在序列化时写入派生类型的元数据,反序列化抽象基类Entity时,无法直接实例化抽象类,导致生成的UnitEntity实例为null,最终在初始化Dictionary<string, UnitEntity>时因为传入null集合触发Value cannot be null. Parameter name: collection错误。
而转为Dictionary<string, object>时,JSON.NET会用JObject存储反序列化结果,直接调用JToken.Value方法时因为未指定具体类型,才会出现方法未实现的提示。
解决方案
方案1:启用类型元数据保留(TypeNameHandling)
通过配置TypeNameHandling,让JSON.NET在序列化时写入类型信息,反序列化时根据元数据识别派生类型,正确实例化对象。
序列化代码(修改原有序列化逻辑)
var serializeSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, // 自动为派生类型添加类型元数据 Formatting = Formatting.Indented // 可选,格式化JSON便于阅读 }; // 假设yourDictionary是要序列化的Dictionary<string, UnitEntity>实例 string jsonContent = JsonConvert.SerializeObject(yourDictionary, serializeSettings); File.WriteAllText(filePath, jsonContent);
反序列化代码
var deserializeSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto // 安全提示:如果担心类型注入风险,可限制允许的类型,例如自定义SerializationBinder }; string factionEntityJson = File.ReadAllText(filePath); Dictionary<string, UnitEntity> entity = JsonConvert.DeserializeObject<Dictionary<string, UnitEntity>>(factionEntityJson, deserializeSettings);
方案2:自定义JsonConverter(无需类型元数据)
如果不想在JSON中写入类型元数据,可自定义转换器,强制将基类Entity反序列化为UnitEntity实例(适用于确定基类只有这一种派生类的场景)。
自定义转换器代码
public class EntityToUnitConverter : JsonConverter<Entity> { public override Entity ReadJson(JsonReader reader, Type objectType, Entity existingValue, bool hasExistingValue, JsonSerializer serializer) { // 直接反序列化为UnitEntity return serializer.Deserialize<UnitEntity>(reader); } public override void WriteJson(JsonWriter writer, Entity value, JsonSerializer serializer) { // 序列化时按UnitEntity处理 serializer.Serialize(writer, value as UnitEntity); } }
使用转换器的序列化/反序列化代码
// 序列化 var settings = new JsonSerializerSettings { Converters = new List<JsonConverter> { new EntityToUnitConverter() }, Formatting = Formatting.Indented }; string jsonContent = JsonConvert.SerializeObject(yourDictionary, settings); File.WriteAllText(filePath, jsonContent); // 反序列化 string factionEntityJson = File.ReadAllText(filePath); Dictionary<string, UnitEntity> entity = JsonConvert.DeserializeObject<Dictionary<string, UnitEntity>>(factionEntityJson, settings);
额外检查项
- 确保
Entity和UnitEntity类有公共无参构造函数,如果使用私有构造函数,需为其添加[JsonConstructor]特性,让JSON.NET可以调用。 - 检查类中是否有未公开的字段/属性,或者循环引用(可通过配置
ReferenceLoopHandling.Ignore解决循环引用问题)。
内容的提问来源于stack exchange,提问作者NeoKuro
相关产品推荐
相关产品推荐

