
当使用自定义 jackson `stdserializer` 处理多态集合(如 `list
在 Jackson(尤其是 XmlMapper)中实现多态序列化时,一个常见误区是:在自定义序列化器中手动写入字段名但未真正序列化对象内容。例如原代码中使用:
jg.writeNullField(animal.getClass().getSimpleName());
该方法仅生成一个空标签(如
✅ 正确做法是利用 Jackson 提供的 委托序列化机制 —— 调用 JsonGenerator#writeObjectField(String fieldName, Object value)。此方法会自动触发 Jackson 对 value 的标准序列化逻辑(包括字段发现、注解处理、类型适配等),从而保留 Dog 类中所有可序列化的公共字段(或按 @JsonProperty 配置的字段)。
以下是修复后的 ZooSerializer 完整实现:
public class ZooSerializer extends StdSerializer{ public ZooSerializer() { this(null); } public ZooSerializer(Class t) { super(t); } @Override public void serialize(Zoo zoo, JsonGenerator jg, SerializerProvider sp) throws IOException { jg.writeStartObject(); for (Animal animal : zoo.animals) { String typeName = animal.getClass().getSimpleName(); jg.writeObjectField(typeName, animal); // ✅ 关键:委托 Jackson 序列化 animal 实例 } jg.writeEndObject(); } }
运行测试后,输出将变为符合预期的 XML 结构:
Collie 6
⚠️ 重要注意事项:
- 此方案依赖 Jackson 的默认 POJO 序列化规则(如字段可见性、@JsonProperty、@JsonIgnore 等),请确保 Dog 等子类字段满足可访问要求(默认 public 字段或配有 getter)。
- 由于未启用 @JsonTypeInfo(如 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME)),Jackson 在反序列化时无法自动识别
标签对应的具体子类类型 。若需反序列化 XML 回 Zoo 对象,必须配套实现自定义 JsonDeserializer,解析 XML 元素名并手动实例化对应子类。 - 若项目允许,更推荐使用 Jackson 内置的多态支持(如 @JsonTypeInfo + @JsonSubTypes),可避免手写序列化/反序列化器,提升可维护性与健壮性。
总之,writeObjectField() 是连接自定义结构控制与默认序列化能力的关键桥梁——它让你掌控“在哪里写”,而把“怎么写内容”交还给 Jackson,兼顾灵活性与完整性。









