最推荐使用 Jackson XML(XmlMapper)实现 POJO 与 XML 映射,兼容 JDK 8–21,无需 JAXB 依赖;需用 @JacksonXmlRootElement、@JacksonXmlProperty 等注解控制命名与结构,注意命名空间和 CDATA 的特殊处理。

Java中实现XML与POJO映射,最常用且稳定的选择是 JAXB(Java Architecture for XML Binding),但要注意:JDK 11+ 已默认移除 javax.xml.bind 包,必须显式引入依赖;若用 Spring Boot,spring-boot-starter-web 默认含 Jackson 的 jackson-dataformat-xml,它更轻量、支持流式处理,且无 JDK 版本绑定问题。
用 Jackson XML 实现 POJO ↔ XML(推荐)
适用于 Spring 生态或纯 Java 项目,无需额外配置 JAXB 模块,兼容 JDK 8–21,序列化/反序列化行为更可控。
-
@JacksonXmlRootElement必须加在根类上,否则反序列化会抛InvalidDefinitionException: Cannot construct instance - 字段名默认按驼峰转短横线(
userName→),如需保持原名,加@JacksonXmlProperty(localName = "userName") - 集合字段需配合
@JacksonXmlElementWrapper(useWrapping = false)控制是否包裹外层标签 - 空值处理:默认不输出 null 字段;如需保留,加
@JsonInclude(JsonInclude.Include.ALWAYS)
ObjectMapper xmlMapper = new XmlMapper();
// 启用忽略未知字段,避免因XML多出标签而失败
xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
User user = xmlMapper.readValue("123 Alice ", User.class);
String xml = xmlMapper.writeValueAsString(user);
JAXB 在 JDK 8–10 中的直接使用
仅限老项目或明确要求标准 JSR-222 接口的场景。JDK 11 起已废弃,硬用会报 NoClassDefFoundError: javax/xml/bind/JAXBContext。
- POJO 需加
@XmlRootElement,字段加@XmlElement(非必需,但建议显式声明) -
JAXBContext.newInstance(User.class)是关键入口,不能传 null 或接口 - 反序列化时若 XML 根元素名与类注解不一致,会抛
UnmarshalException: unexpected element - 不支持泛型集合直接映射(如
List),需包装成带@XmlRootElement的容器类
JAXBContext context = JAXBContext.newInstance(User.class); Unmarshaller unmarshaller = context.createUnmarshaller(); User user = (User) unmarshaller.unmarshal(new StringReader(xmlStr));
处理命名空间和 CDATA 的常见坑
真实业务 XML 常含 xmlns 或 ,这两类问题容易被忽略导致解析失败。
立即学习“Java免费学习笔记(深入)”;
- Jackson XML 默认不处理命名空间;如需支持,得设
xmlMapper.setDefaultUseWrapper(false)并手动配置XmlFactory启用命名空间感知 - CDATA 内容会被自动转义为普通文本;若需原样保留,字段加
@JacksonXmlText并确保该字段类型为String - JAXB 对 CDATA 无原生支持,需自定义
XmlAdapter,例如将String转为含的字符串 - 含多个同名子节点(如
- ...
多次出现)时,Jackson 要求字段为List且加@JacksonXmlElementWrapper(useWrapping = false),否则只取第一个
实际选型时,别纠结“标准”或“老派”,优先看运行环境——JDK 版本、是否已有 Jackson 依赖、是否要处理流式大文件。JAXB 灵活性低、维护停滞;Jackson XML 更贴近现代开发节奏,但得记住:它的默认命名策略和空值行为跟 JAXB 不同,迁移时务必验证生成的 XML 结构是否符合下游系统契约。










