JsonConvert反序列化抽象类数组失败,如何指定具体类型?
解决Json.NET反序列化抽象类数组的问题
这个坑我之前踩过!Json.NET默认没法直接把抽象类/接口反序列化成具体实例,因为它不知道该选哪个实现类。给你几个靠谱的解决办法,按需选就行:
方法一:用TypeNameHandling自动记录类型信息
这个是最简单的,让Json.NET在序列化的时候把具体类型的信息写到JSON里,反序列化的时候就读取这个信息来实例化正确的类。
两种使用方式:
- 给属性加特性:直接在Street类的Buildings属性上标注,指定ItemTypeNameHandling:
public class Street { // 告诉Json.NET要记录数组元素的具体类型 [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)] public Building[] Buildings { get; set; } }
- 全局序列化配置:如果不想改实体类,也可以在序列化和反序列化的时候统一设置:
// 序列化时带上类型信息 var json = JsonConvert.SerializeObject(yourStreetObject, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }); // 反序列化时读取类型信息 var deserializedStreet = JsonConvert.DeserializeObject<Street>(json, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
⚠️ 注意:这个方式会在JSON里多出一个$type字段,记录具体类型的命名空间和类名。如果你的JSON来自不可信的外部来源,别用这个,有安全风险(可能被注入恶意类型)。
方法二:自定义JsonConverter(更安全灵活)
如果确定Buildings数组里只会有Flat实例,或者需要自己控制类型判断逻辑,写个自定义转换器是最好的选择。
步骤:
- 写一个继承自
JsonConverter<Building>的转换器:
public class BuildingConverter : JsonConverter<Building> { // 反序列化时直接实例化Flat public override Building ReadJson(JsonReader reader, Type objectType, Building existingValue, bool hasExistingValue, JsonSerializer serializer) { // 这里可以根据JSON里的字段判断要实例化哪个具体类 // 比如如果有WhichFloor字段就返回Flat,其他情况返回别的实现 return serializer.Deserialize<Flat>(reader); } // 序列化时正常处理具体类型 public override void WriteJson(JsonWriter writer, Building value, JsonSerializer serializer) { serializer.Serialize(writer, value); } }
- 使用转换器:
- 方式一:给抽象类Building加特性,全局生效:
[JsonConverter(typeof(BuildingConverter))] public abstract class Building { // 你的抽象类成员 }- 方式二:在反序列化时单独指定:
var settings = new JsonSerializerSettings { Converters = new List<JsonConverter> { new BuildingConverter() } }; var deserializedStreet = JsonConvert.DeserializeObject<Street>(json, settings);
这个方式不会在JSON里加额外字段,而且完全由你控制类型实例化逻辑,安全性更高,推荐在生产环境用。
内容的提问来源于stack exchange,提问作者Sun
相关产品推荐
相关产品推荐

