无法将XML转换为POJO,解析时引用链出现异常
XML转POJO解析失败的解决方案(Jackson XmlMapper)
问题背景
从Web服务获取的XML响应无法通过Jackson XmlMapper转换为POJO,报错信息如下:
test failed Unrecognized field "Step" (class com.adapters.ccr.ApaData), not marked as ignorable (3 known properties: "processCode", "processLabel", "steps"]) at [Source: (StringReader); line: 6, column: 18] (through reference chain: com.adapters.ccr.ApaData["Step"])
核心矛盾:预期XML包含<Steps>父标签,但实际响应中直接是多个<Step>元素,同时存在字段名大小写不匹配、XML命名空间未处理的问题。
原POJO类
public class ApaData { private String processCode; private String processLabel; private List<Step> steps; } public class Step { private Integer StepNum; private String StepStatus; private String StepLabel; }
实际XML响应
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <APA_Data xmlns="http://www.test.com/atlas/apa/v1"> <ProcessCode>4</ProcessCode> <ProcessLabel>information is invalid.</ProcessLabel> <Step> <StepNum>1</StepNum> <StepStatus>9</StepStatus> <StepLabel>Decryption not attempted.</StepLabel> </Step> <Step> <StepNum>2</StepNum> <StepStatus>9</StepStatus> <StepLabel>Digital signature verification not attempted.</StepLabel> </Step> </APA_Data>
解决方案
通过Jackson的XML注解调整POJO映射规则,同时处理命名空间和列表包装问题:
修改后的POJO类
ApaData类
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import java.util.List; @JacksonXmlRootElement(localName = "APA_Data", namespace = "http://www.test.com/atlas/apa/v1") public class ApaData { @JacksonXmlProperty(localName = "ProcessCode", namespace = "http://www.test.com/atlas/apa/v1") private String processCode; @JacksonXmlProperty(localName = "ProcessLabel", namespace = "http://www.test.com/atlas/apa/v1") private String processLabel; @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "Step", namespace = "http://www.test.com/atlas/apa/v1") private List<Step> steps; // 必须添加Getter/Setter方法,Jackson依赖反射访问字段 public String getProcessCode() { return processCode; } public void setProcessCode(String processCode) { this.processCode = processCode; } public String getProcessLabel() { return processLabel; } public void setProcessLabel(String processLabel) { this.processLabel = processLabel; } public List<Step> getSteps() { return steps; } public void setSteps(List<Step> steps) { this.steps = steps; } }
Step类
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class Step { @JacksonXmlProperty(localName = "StepNum", namespace = "http://www.test.com/atlas/apa/v1") private Integer stepNum; @JacksonXmlProperty(localName = "StepStatus", namespace = "http://www.test.com/atlas/apa/v1") private String stepStatus; @JacksonXmlProperty(localName = "StepLabel", namespace = "http://www.test.com/atlas/apa/v1") private String stepLabel; // Getter/Setter方法 public Integer getStepNum() { return stepNum; } public void setStepNum(Integer stepNum) { this.stepNum = stepNum; } public String getStepStatus() { return stepStatus; } public void setStepStatus(String stepStatus) { this.stepStatus = stepStatus; } public String getStepLabel() { return stepLabel; } public void setStepLabel(String stepLabel) { this.stepLabel = stepLabel; } }
关键注解说明
@JacksonXmlRootElement:绑定XML根节点名称和命名空间,与响应中的<APA_Data>完全匹配。@JacksonXmlProperty:解决POJO驼峰字段与XML大写字段的映射问题,同时指定命名空间避免解析失败。@JacksonXmlElementWrapper(useWrapping = false):核心配置,告诉Jackson不需要为列表寻找父标签(如<Steps>),直接将所有<Step>元素收集到steps列表中。
简化配置(忽略命名空间)
如果不想每个字段都指定命名空间,可以通过XmlMapper配置全局忽略命名空间:
import com.fasterxml.jackson.dataformat.xml.XmlMapper; public class XmlParser { public static void main(String[] args) throws Exception { XmlMapper xmlMapper = XmlMapper.builder() .configure(com.fasterxml.jackson.dataformat.xml.XmlParser.Feature.IGNORE_NAMESPACE, true) .build(); // 后续解析代码不变 ApaData data = xmlMapper.readValue(xmlString, ApaData.class); } }
此时POJO注解中的namespace参数可以省略,进一步简化代码。
测试验证
运行修改后的解析代码,即可成功将XML转换为ApaData对象,获取所有字段和步骤数据。
内容的提问来源于stack exchange,提问作者Grafana Next
相关产品推荐
相关产品推荐

