自定义Jackson序列化器包装类无法序列化子类字段问题
问题:子类字段在XML序列化时未被输出(Zoo容器场景)
我需要将一组类层级结构序列化为XML。参考过往帖子实现了子类以正确类名序列化,但子类字段未被序列化。示例代码中,单独序列化Dog对象时能输出breed和age字段,但将Dog加入Zoo后,序列化Zoo仅得到空的
代码示例
实体类定义
public abstract class Animal {} public class Dog extends Animal{ public String breed; public String age; public Dog(String breed, String age) { this.breed = breed; this.age = age; } } @JsonSerialize(using = ZooSerializer.class) public class Zoo { public List<Animal> animals = new ArrayList<>(); }
自定义序列化器
public class ZooSerializer extends StdSerializer<Zoo> { public ZooSerializer(Class<Zoo> t) { super(t); } public ZooSerializer() { this(null); } @Override public void serialize(Zoo zoo, JsonGenerator jg, SerializerProvider sp) throws IOException { jg.writeStartObject(); for (Animal animal: zoo.animals) { jg.writeNullField(animal.getClass().getSimpleName()); } jg.writeEndObject(); } }
测试代码
@Test public void Test() { XmlMapper xmlMapper = new XmlMapper(); try { Zoo zoo = new Zoo(); Dog dog = new Dog("Collie", "6"); System.out.println(xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(dog)); zoo.animals.add(dog); System.out.println(xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(zoo)); } catch (JsonProcessingException e) { e.printStackTrace(); } }
输出结果
<Dog> <breed>Collie</breed> <age>6</age> </Dog> <Zoo> <Dog/> </Zoo>
问题原因与解决思路
问题根源
自定义的ZooSerializer中,jg.writeNullField(animal.getClass().getSimpleName())仅写入了一个空的XML标签,并未触发Jackson对Animal子类对象的实际序列化逻辑,因此子类的字段不会被输出。
修正方案
修改ZooSerializer的serialize方法,让Jackson自动序列化每个Animal实例:
public class ZooSerializer extends StdSerializer<Zoo> { public ZooSerializer(Class<Zoo> t) { super(t); } public ZooSerializer() { this(null); } @Override public void serialize(Zoo zoo, JsonGenerator jg, SerializerProvider sp) throws IOException { jg.writeStartObject(); for (Animal animal : zoo.animals) { // 获取对应子类的序列化器 JsonSerializer<Object> serializer = sp.findValueSerializer(animal.getClass(), null); // 序列化当前Animal对象,输出所有字段 serializer.serialize(animal, jg, sp); } jg.writeEndObject(); } }
修正后输出
重新运行测试代码,Zoo的序列化结果会包含Dog的完整字段:
<Zoo> <Dog> <breed>Collie</breed> <age>6</age> </Dog> </Zoo>
额外说明
如果后续新增Cat、Bird等Animal子类,该方案无需修改序列化器,Jackson会自动识别子类类型并调用对应序列化逻辑,保持代码扩展性。
内容的提问来源于stack exchange,提问作者Timothy Clotworthy
相关产品推荐
相关产品推荐

