Spring Boot中Java反序列化XML时无法构造实例问题
XML反序列化Jackson报错:无法从字符串值构造FxRate实例
报错信息
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of <code>com.example.demo.models.responses.FxRate</code> (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('EU')
问题根源
- XML命名空间未处理:返回的XML所有节点都属于
http://www.lb.lt/WebServices/FxRates命名空间,但实体类未配置对应注解,Jackson无法正确识别节点归属 - 集合节点注解缺失:
FxRates中的FxRate集合、FxRate中的CcyAmt集合缺少Jackson XML专属注解,导致Jackson错误将子节点(如<Tp>EU</Tp>)的文本值当作要赋值给FxRate对象的字符串 - 注解使用错误:
xmlns是根节点属性而非子节点,原代码用@JsonProperty标记错误;JsonPropertyOrder配置无效且顺序错误
修正方案及代码
1. 修正FxRates类
package com.example.demo.models.responses; 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 = "FxRates", namespace = "http://www.lb.lt/WebServices/FxRates") public class FxRates { // 关闭集合包装,直接解析同名子节点为集合元素 @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "FxRate", namespace = "http://www.lb.lt/WebServices/FxRates") private List<FxRate> fxRate; // 标记xmlns为节点属性 @JacksonXmlProperty(isAttribute = true, localName = "xmlns") private String xmlns; public FxRates() {} public FxRates(List<FxRate> fxRate, String xmlns) { this.fxRate = fxRate; this.xmlns = xmlns; } // Getter & Setter public List<FxRate> getFxRate() { return fxRate; } public void setFxRate(List<FxRate> fxRate) { this.fxRate = fxRate; } public String getXmlns() { return xmlns; } public void setXmlns(String xmlns) { this.xmlns = xmlns; } }
2. 修正FxRate类
package com.example.demo.models.responses; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import java.util.List; public class FxRate { @JacksonXmlProperty(localName = "Tp", namespace = "http://www.lb.lt/WebServices/FxRates") private String tp; @JacksonXmlProperty(localName = "Dt", namespace = "http://www.lb.lt/WebServices/FxRates") private String dt; @JacksonXmlElementWrapper(useWrapping = false) @JacksonXmlProperty(localName = "CcyAmt", namespace = "http://www.lb.lt/WebServices/FxRates") private List<CcyAmt> ccyAmt; public FxRate() {} public FxRate(String tp, String dt, List<CcyAmt> ccyAmt) { this.tp = tp; this.dt = dt; this.ccyAmt = ccyAmt; } // Getter & Setter public String getTp() { return tp; } public void setTp(String tp) { this.tp = tp; } public String getDt() { return dt; } public void setDt(String dt) { this.dt = dt; } public List<CcyAmt> getCcyAmt() { return ccyAmt; } public void setCcyAmt(List<CcyAmt> ccyAmt) { this.ccyAmt = ccyAmt; } }
3. 修正CcyAmt类
package com.example.demo.models.responses; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; public class CcyAmt { @JacksonXmlProperty(localName = "Ccy", namespace = "http://www.lb.lt/WebServices/FxRates") private String ccy; @JacksonXmlProperty(localName = "Amt", namespace = "http://www.lb.lt/WebServices/FxRates") private String amt; public CcyAmt() {} public CcyAmt(String ccy, String amt) { this.ccy = ccy; this.amt = amt; } // Getter & Setter public String getCcy() { return ccy; } public void setCcy(String ccy) { this.ccy = ccy; } public String getAmt() { return amt; } public void setAmt(String amt) { this.amt = amt; } }
4. 优化Controller中的XmlMapper配置
添加忽略未知节点的配置,避免因XML新增节点导致反序列化失败:
XmlMapper xmlMapper = XmlMapper.builder() .configure(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .build();
内容的提问来源于stack exchange,提问作者Skully1
相关产品推荐
相关产品推荐

