Jackson非抽象父类多态反序列化问题:无法使用@JsonTypeInfo注解
非抽象父类的Jackson多态反序列化解决方案(无需修改JSON)
因为没法修改已有的JSON,也用不了@JsonTypeInfo注解,给你两个可行的解决思路:
方案一:自定义反序列化器手动识别子类
核心思路是靠JSON里的子类独有字段判断类型(比如Dog有barkVolume、Cat有meowPitch),写个自定义反序列化器来处理:
1. 编写自定义反序列化器
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; public class AnimalDeserializer extends StdDeserializer<Animal> { public AnimalDeserializer() { super(Animal.class); } @Override public Animal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); // 按实际子类的独有字段调整判断逻辑 if (node.has("barkVolume")) { return p.getCodec().treeToValue(node, Dog.class); } else if (node.has("meowPitch")) { return p.getCodec().treeToValue(node, Cat.class); } // 没有子类字段时返回父类实例 return p.getCodec().treeToValue(node, Animal.class); } }
2. 给父类绑定反序列化器
在Animal类上加注解,指定使用上面的自定义反序列化器:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @JsonDeserialize(using = AnimalDeserializer.class) public class Animal { // 父类原有字段、方法 }
方案二:全局配置ObjectMapper(无需修改父类)
不想给Animal类加注解的话,可以全局修改ObjectMapper的反序列化逻辑:
1. 配置自定义模块
import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier; import com.fasterxml.jackson.databind.module.SimpleModule; public class AnimalMapperConfig { public static ObjectMapper getAnimalMapper() { ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.setDeserializerModifier(new BeanDeserializerModifier() { @Override public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) { // 拦截Animal类的反序列化,替换成自定义逻辑 if (beanDesc.getBeanClass() == Animal.class) { return new AnimalDeserializer(); } return super.modifyDeserializer(config, beanDesc, deserializer); } }); mapper.registerModule(module); return mapper; } }
2. 使用配置好的ObjectMapper
// 用这个配置好的mapper来反序列化JSON ObjectMapper mapper = AnimalMapperConfig.getAnimalMapper(); Animal animal = mapper.readValue(jsonStr, Animal.class);
注意事项
- 子类的独有字段必须唯一,不能多个子类共用同名字段,否则判断逻辑会出错。
- 后续新增子类时,只需要在
AnimalDeserializer里新增对应的字段判断分支即可。 - 如果JSON里没有任何子类特有字段,会自动返回Animal父类实例,避免反序列化失败。
内容的提问来源于stack exchange,提问作者dh1
相关产品推荐
相关产品推荐

