You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:50:30