
本文详解如何使用 Jackson 的 @JacksonXmlElementWrapper(useWrapping = false) 与 @JacksonXmlProperty 组合,实现 POJO 列表字段在 XML 输出中无包装标签(如 )的扁平化序列化。
本文详解如何使用 jackson 的 `@jacksonxmlelementwrapper(usewrapping = false)` 与 `@jacksonxmlproperty` 组合,实现 pojo 列表字段在 xml 输出中无包装标签(如 `
在基于 Jackson 进行 XML 序列化(jackson-dataformat-xml)时,一个常见需求是:将 Java 中的 List
✅ 正确配置方式
核心在于对 List
- @JacksonXmlElementWrapper(useWrapping = false):禁用外层包装节点(即不生成
); - @JacksonXmlProperty(localName = "my_child"):显式指定每个列表元素应使用的 XML 标签名(即每个 Child 实例渲染为
)。
⚠️ 注意:@JacksonXmlProperty 必须标注在字段上(而非类或 getter),且 localName 值需与你期望的子元素名完全一致;Child 类本身无需任何 Jackson XML 注解(除非需自定义其内部字段映射)。
以下是精简、可运行的完整示例:
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
import com.fasterxml.jackson.annotation.*;
import java.util.List;
@JacksonXmlRootElement(localName = "my_company")
public class Company {
public String comName;
public String comEmail;
// ✅ 关键:双注解协同生效
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "my_child")
public List<Child> childs;
public Company(String comName, String comEmail, List<Child> childs) {
this.comName = comName;
this.comEmail = comEmail;
this.childs = childs;
}
// 子类无需额外注解(除非需多态或重命名)
public static class Child {
public String street;
public String state;
public String city;
public Child(String street, String state, String city) {
this.street = street;
this.state = state;
this.city = city;
}
}
// 测试入口
public static void main(String[] args) throws Exception {
List<Child> children = List.of(
new Child("Main St", "CA", "San Francisco"),
new Child("Oak Ave", "NY", "New York")
);
Company company = new Company("TechCorp", "contact@techcorp.com", children);
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.enable(ToXmlGenerator.Feature.WRITE_XML_DECLARATION);
xmlMapper.writerWithDefaultPrettyPrinter()
.writeValue(System.out, company);
}
}运行后输出符合预期的扁平化 XML:
<?xml version='1.0' encoding='UTF-8'?>
<my_company>
<comName>TechCorp</comName>
<comEmail>contact@techcorp.com</comEmail>
<my_child>
<street>Main St</street>
<state>CA</state>
<city>San Francisco</city>
</my_child>
<my_child>
<street>Oak Ave</street>
<state>NY</state>
<city>New York</city>
</my_child>
</my_company>? 常见误区与注意事项
-
勿遗漏 @JacksonXmlProperty:仅设 useWrapping = false 会导致 Jackson 使用字段名(如 childs)作为每个子元素名,输出
—— 这并非扁平化,而是错误降级。... ... - 避免嵌套泛型或复杂继承干扰:原问题中 Parent 抽象类及 @JsonTypeInfo 在 XML 场景下非必需,且易引发类型解析歧义;如确需多态 XML,应改用 @JsonSubTypes + @JsonTypeName 配合 @JacksonXmlDiscriminator(Jackson 2.12+),但本场景纯扁平列表无需此复杂度。
- 字段可见性要求:确保字段为 public 或提供 public getter/setter,否则需配置 Visibility 或启用 @JsonAutoDetect。
- 依赖版本建议:使用 jackson-dataformat-xml ≥ 2.12,并确认 XmlMapper 已正确初始化(推荐通过 new XmlMapper() 而非 new ObjectMapper().registerModule(new JaxbAnnotationModule()))。
掌握这一组合注解模式,即可优雅解决 Jackson XML 中列表扁平化的核心诉求,显著提升生成 XML 的语义清晰度与下游系统兼容性。










