使用JAXB解组XML时Body.content未正确映射为目标对象问题
问题:JAXB解组XML时未将子节点映射为对应Java对象
现有Java类定义
Data与Body类
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Data", propOrder = { "body" }) @XmlRootElement(name = "Data") class Data { @XmlElement(name = "Body", required = true) protected Body body; // getter and setter } @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Body", propOrder = { "content" }) class Body { @XmlMixed @XmlAnyElement protected List<Object> content; // getter }
Node1与Node2类
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Node1", propOrder = { "data", }) class Node1 { @XmlElement(name = "Data") private String data; } @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Node2", propOrder = { "int", }) class Node2 { @XmlElement(name = "Int") private Integer int; }
XML示例
<Data> <Body> <Node1> <Data>abc</Data> </Node1> <Node2> <Int>abc</Int> </Node2> </Body> </Data>
解组代码
private Object xmlToObject(String xmlString) throws Exception { var context = JAXBContext.newInstance(Data.class, Node1.class, Node2.class); var unmarshaller = context.createUnmarshaller(); return unmarshaller.unmarshal(new StringReader(xmlString)); }
问题现象
预期:解组后得到包含Body对象的Data实例,Body的content集合中包含Node1和Node2类型对象。
实际:Body.content中的元素为ElementNSimpl类型对象及含换行的字符串,未映射为目标Java类实例。
解决方案
原因分析
@XmlAnyElement默认会将未匹配的XML元素解析为DOM节点(ElementNSimpl),@XmlMixed会把XML中的文本节点(包括换行、空格)也加入集合,两者叠加导致当前结果。要让JAXB自动映射Node1/Node2,需调整注解配置。
修正方案
方案1:仅保留子节点对象(移除文本内容)
如果不需要保留Body中的换行、空格等文本内容,直接修改Body类的注解:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Body", propOrder = { "content" }) class Body { @XmlAnyElement(lax = true) // 关键:添加lax=true属性 protected List<Object> content; // getter }
lax=true会让JAXB尝试将XML元素映射到JAXBContext已注册的类(Node1、Node2),匹配成功则返回对应Java对象,否则返回DOM节点。同时移除@XmlMixed,避免文本节点混入集合。
方案2:保留混合内容(文本+子节点)
如果必须保留文本内容,需保留@XmlMixed并配合@XmlAnyElement(lax=true),但集合中仍会包含文本对象,后续需自行过滤。另外注意Node2类的字段名int是Java关键字,建议改为intValue等合法名称,避免编译报错。
验证
修改后重新运行解组代码,Body.content集合中将出现Node1和Node2的实例,而非ElementNSimpl对象。
内容的提问来源于stack exchange,提问作者bobrik
相关产品推荐
相关产品推荐

