如何在JAXB生成的XML响应中包含空列表
让JAXB在List为null时生成带xsi:nil="true"的元素(无额外包裹标签)
问题场景
使用CXF SOAP服务结合JAXB编组器,通过wsdl2java生成的存根类如下:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "ResultOperation", propOrder = { "result", "ElementList" }) public class ResultOperation { @XmlElement(nillable = true) protected Result result; @XmlElement(nillable = true) protected List<ElementList> elementList; // getters, setters... }
当elementList为null时,期望生成的XML包含<ns4:elementList xsi:nil="true"/>,但实际响应中该元素被省略。@XmlElementWrapper(nillable = true)会添加额外包裹标签,不符合需求。
可行解决方案
方案1:将List替换为数组(推荐,无需自定义代码)
JAXB对数组类型的@XmlElement(nillable=true)支持更符合需求:当数组为null时,会自动生成带xsi:nil="true"的元素,非null时直接输出数组元素,无包裹标签。
实现方式:
- 创建JAXB绑定文件(如
binding.xml),指定目标元素生成数组而非List:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="2.1"> <!-- 针对ResultOperation中的elementList元素设置数组类型 --> <jaxb:bindings node="//xsd:complexType[@name='ResultOperation']/xsd:sequence/xsd:element[@name='elementList']"> <jaxb:property collectionType="array"/> </jaxb:bindings> </jaxb:bindings>
- 重新执行wsdl2java命令生成存根类:
wsdl2java -b binding.xml your-service.wsdl
生成的存根类中elementList会变为ElementList[]类型,保留@XmlElement(nillable=true)注解,此时数组为null时即可输出目标XML元素。
方案2:用JAXBElement包裹List
通过JAXBElement包裹List,让JAXB识别null值并生成xsi:nil属性,同时避免包裹标签。
实现方式:
- 修改存根类的
elementList字段为JAXBElement<List<ElementList>>:
@XmlElement(nillable = true) protected JAXBElement<List<ElementList>> elementList;
- 当需要输出
xsi:nil时,构造空值的JAXBElement实例:
// 替换为实际的命名空间和元素名 QName elementQName = new QName("http://your-target-namespace", "elementList"); JAXBElement<List<ElementList>> nilElement = new JAXBElement<>( elementQName, new TypeReference<List<ElementList>>() {}, null ); resultOperation.setElementList(nilElement);
当List非空时,只需构造带List值的JAXBElement即可正常输出元素。
如果不想手动修改存根类,也可以通过绑定文件让wsdl2java自动生成JAXBElement包裹的字段:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="2.1"> <jaxb:bindings node="//xsd:complexType[@name='ResultOperation']/xsd:sequence/xsd:element[@name='elementList']"> <jaxb:property> <jaxb:baseType name="javax.xml.bind.JAXBElement"/> </jaxb:property> </jaxb:bindings> </jaxb:bindings>
方案3:自定义XmlAdapter(灵活但需额外代码)
创建XmlAdapter自定义List的编组逻辑,强制在List为null时生成带xsi:nil的元素:
public class ListNilAdapter extends XmlAdapter<ListNilAdapter.Wrapper, List<ElementList>> { public static class Wrapper { @XmlElement(name = "elementList", nillable = true) public List<ElementList> items; } @Override public List<ElementList> unmarshal(Wrapper v) throws Exception { return v != null ? v.items : null; } @Override public Wrapper marshal(List<ElementList> v) throws Exception { Wrapper wrapper = new Wrapper(); wrapper.items = v; return wrapper; } }
然后在存根类的elementList字段添加注解:
@XmlElement(nillable = true) @XmlJavaTypeAdapter(ListNilAdapter.class) protected List<ElementList> elementList;
此方法通过包装类让JAXB识别null值并生成xsi:nil属性,同时保持输出格式符合要求。
内容的提问来源于stack exchange,提问作者Andrey
相关产品推荐
相关产品推荐

