使用JAXB编组时,如何抑制可空元素的nil输出?
我完全懂你遇到的这个情况——当用JAXB处理带nillable="true"的XSD元素时,空值下自动输出xsi:nil="true"虽然符合XML Schema规范,但有时候就是不想让它出现,想跟那些只设了minOccurs="0"的非nillable元素(比如你的LOG_TXNDTLLTY)一样,空值时直接不生成这个元素对吧?
下面给你几种实用的解决办法,根据你的场景选就行:
方法1:从XSD生成Java类时配置绑定规则
如果你是通过XSD自动生成Java实体类,可以写一个JAXB绑定文件(比如binding.xjb),直接修改nillable元素的生成行为:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- 全局设置:让所有nillable元素空值时不输出nil标记 --> <jaxb:globalBindings> <jaxb:nillable /> </jaxb:globalBindings> <!-- 或者只针对单个元素(比如CAPTURE_ADDRESS)精准配置 --> <jaxb:bindings schemaLocation="你的XSD文件路径.xsd"> <jaxb:bindings node="//xs:element[@name='CAPTURE_ADDRESS']"> <jaxb:property> <jaxb:nillable>false</jaxb:nillable> </jaxb:property> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings>
生成Java类的时候指定这个绑定文件,这样生成的CAPTURE_ADDRESS字段就会和LOG_TXNDTLLTY一样,空值时直接不生成元素。
方法2:直接修改已生成的Java类
如果已经有现成的Java实体类了,不用重新生成的话,可以直接在字段上改注解:
找到CAPTURE_ADDRESS对应的字段,把默认生成的@XmlElement(nillable = true)改成nillable = false:
@XmlElement(name = "CAPTURE_ADDRESS", nillable = false) protected PCMSBOOLEANType captureAddress;
这样当captureAddress为null时,编组XML就不会输出这个元素了。
方法3:全局配置Marshaller属性
如果想一次性搞定所有nillable元素的问题,可以在创建Marshaller的时候设置属性:
针对JAXB RI(默认实现)
Marshaller marshaller = jaxbContext.createMarshaller(); // 禁止输出nil元素,空值时直接忽略 marshaller.setProperty("com.sun.xml.bind.nillable", false);
针对EclipseLink MOXy
如果你用的是MOXy作为JAXB实现,属性名不一样:
Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(org.eclipse.persistence.jaxb.MarshallerProperties.NILLABLE, false);
这个设置是全局的,所有nillable元素空值时都会被忽略,不会生成带xsi:nil的元素。
方法4:用XmlAdapter做灵活控制
如果需要更精细的控制(比如某些nillable元素要输出nil,某些不要),可以自定义一个XmlAdapter:
public class NullSkipAdapter extends XmlAdapter<PCMSBOOLEANType, PCMSBOOLEANType> { @Override public PCMSBOOLEANType unmarshal(PCMSBOOLEANType v) throws Exception { return v; } @Override public PCMSBOOLEANType marshal(PCMSBOOLEANType v) throws Exception { // 空值时返回null,Marshaller就不会生成这个元素 return v == null ? null : v; } }
然后在需要控制的字段上加上这个适配器注解:
@XmlElement(name = "CAPTURE_ADDRESS") @XmlJavaTypeAdapter(NullSkipAdapter.class) protected PCMSBOOLEANType captureAddress;
小提醒:
nillable="true"的本意是明确表示“这个元素存在但没有值”,而minOccurs="0"是“这个元素可能不存在”。你选择抑制nil输出的话,相当于把nillable元素的行为改成了后者,要确保对接的系统能接受这个逻辑哦。
内容的提问来源于stack exchange,提问作者Dawn Topping

