Jackson继承反序列化引发无限循环的解决方案咨询
解决Jackson自定义反序列化器无限循环与冗余类问题
核心问题
无法通过@JsonSubTypes处理给定格式的JSON,自定义AnimalDeserializer中return codec.treeToValue(node, Animal.class)语句触发无限循环;当前通过将Animal设为抽象类并新增DefaultAnimal类规避,但会产生冗余类,需更优方案。
给定JSON(不可修改):
[ { "name": "dog name", "type": "dog", "age": 5 }, { "name": "cat name", "type": "cat", "color": "black" } ]
修正后基础类定义(移除Dog类重复的name字段):
class Animal { String name; } class Dog extends Animal { int age; }
优化方案一:手动构建Animal实例,避免递归调用
直接解析JsonNode手动创建并填充Animal对象,不调用codec.treeToValue触发自定义反序列化器,从根源避免循环。
修改后的AnimalDeserializer:
public class AnimalDeserializer extends StdDeserializer<Animal> { public AnimalDeserializer() { super(Animal.class); } @Override public Animal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { ObjectCodec codec = p.getCodec(); JsonNode node = codec.readTree(p); JsonNode typeNode = node.get("type"); if (typeNode != null && !typeNode.isNull()) { String typeText = typeNode.asText(); if ("dog".equals(typeText)) { return codec.treeToValue(node, Dog.class); } // 可扩展其他类型,比如Cat } // 手动构建Animal实例,不触发自定义反序列化器 Animal animal = new Animal(); if (node.has("name")) { animal.name = node.get("name").asText(); } return animal; } }
在Animal类绑定反序列化器:
@JsonDeserialize(using = AnimalDeserializer.class) class Animal { String name; }
优化方案二:使用默认BeanDeserializer绕过自定义逻辑
从DeserializationContext获取Jackson默认的BeanDeserializer处理Animal类,绕过自定义反序列化器,避免循环调用。
修改后的AnimalDeserializer:
public class AnimalDeserializer extends StdDeserializer<Animal> { private final BeanDeserializer defaultDeserializer; public AnimalDeserializer(BeanDeserializer defaultDeserializer) { super(Animal.class); this.defaultDeserializer = defaultDeserializer; } @Override public Animal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { ObjectCodec codec = p.getCodec(); JsonNode node = codec.readTree(p); JsonNode typeNode = node.get("type"); if (typeNode != null && !typeNode.isNull()) { String typeText = typeNode.asText(); if ("dog".equals(typeText)) { // 将JsonNode转回JsonParser,避免位置异常 JsonParser nodeParser = node.traverse(codec); nodeParser.nextToken(); return ctxt.readValue(nodeParser, Dog.class); } } // 使用默认反序列化器处理Animal,不触发自定义逻辑 JsonParser nodeParser = node.traverse(codec); nodeParser.nextToken(); return defaultDeserializer.deserialize(nodeParser, ctxt); } }
通过SimpleModule注册时传入默认反序列化器:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); // 获取Animal的默认BeanDeserializer BeanDeserializer defaultDeserializer = (BeanDeserializer) mapper.getDeserializationConfig() .getDeserializerProvider() .findValueDeserializer(mapper.constructType(Animal.class)); module.addDeserializer(Animal.class, new AnimalDeserializer(defaultDeserializer)); mapper.registerModule(module);
优化方案三:修复@JsonSubTypes配置(优先推荐)
若之前@JsonSubTypes配置错误,可通过正确配置实现自动反序列化,无需自定义反序列化器。
修改Animal类:
@JsonTypeInfo( use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type" // 指定JSON中的类型字段 ) @JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"), // 可添加其他类型,比如Cat.class对应"cat" }) class Animal { String name; }
直接用ObjectMapper反序列化:
List<Animal> animals = mapper.readValue(jsonString, new TypeReference<List<Animal>>() {});
内容的提问来源于stack exchange,提问作者evol1102
相关产品推荐
相关产品推荐

