如何使用Jackson对缺失类型标识属性的子类型进行反序列化?
media_type字段的TvCredits解决方案 问题根源
你遇到的InvalidTypeIdException,本质是因为TvCrew实现了带有@JsonTypeInfo注解的Crew接口。即使TvCredits中明确声明了crew字段是List<TvCrew>,Jackson仍会继承接口的类型解析规则,尝试读取media_type属性来匹配子类型,但第二种API响应的JSON中不存在该字段,导致类型解析失败。
解决方案(无冗余代码)
方案1:在TvCrew类上禁用类型检查
直接在TvCrew类上添加@JsonTypeInfo(use = JsonTypeInfo.Id.NONE),覆盖接口的类型解析规则,告诉Jackson直接反序列化为TvCrew,无需寻找类型ID:
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE) public class TvCrew implements Crew { // 原有字段、方法实现 }
优点:一劳永逸,所有直接使用TvCrew的场景都不会触发类型ID检查;缺点:如果有其他场景需要将TvCrew作为Crew接口的实现进行多态反序列化,会受到影响。
方案2:在TvCredits的crew字段上指定反序列化目标
无需修改TvCrew,仅在TvCredits的crew字段上添加@JsonDeserialize(contentAs = TvCrew.class),明确告诉Jackson该列表的元素直接反序列化为TvCrew:
public class TvCredits { @JsonDeserialize(contentAs = TvCrew.class) private List<TvCrew> crew; // Getter、Setter等方法 }
优点:灵活性高,仅影响TvCredits的反序列化逻辑,不干扰TvCrew在其他场景的使用;缺点:需要针对特定字段添加注解。
方案3:给Crew接口添加默认实现
修改Crew接口的@JsonTypeInfo注解,添加defaultImpl = TvCrew.class,指定当找不到media_type字段时,默认使用TvCrew作为反序列化目标:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "media_type", defaultImpl = TvCrew.class) @JsonSubTypes({ @JsonSubTypes.Type(value = MovieCrew.class, name = "movie"), @JsonSubTypes.Type(value = TvCrew.class, name = "tv") }) public interface Crew { // 原有方法定义 }
优点:无需修改实现类或其他模型类,仅调整接口注解;缺点:如果后续新增其他Crew实现类,需要评估默认值是否合适。
内容的提问来源于stack exchange,提问作者Conor Egan

