You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring RestTemplate搭配JAXB忽略空元素问题(无法修改生成POJO)

问题背景

通过XSD文件自动生成JAXB POJO(示例XSD及生成的POJO如下),使用RestTemplate发送POST请求时,需要忽略值为null/空的元素,但无法直接修改自动生成的POJO类,且升级JAXB、Spring等依赖后原忽略空值的配置失效。

示例XSD

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
  <xs:element name="XYZ">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="A" type="xs:string" minOccurs="0" />
        <xs:element name="B" type="xs:string" minOccurs="0" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

生成的POJO

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "a",
    "b"
})
@XmlRootElement(name = "XYZ")
public class XYZ {
    @XmlElement(name = "A")
    protected String a;
    @XmlElement(name = "B")
    protected String b;
    // 省略getter/setter
}

请求代码

HttpEntity<XYZ> requestHttpEntity = new HttpEntity<>(xyz);
B response;
try {
  ResponseEntity<B> responseEntity = restTemplate.exchange("someAddress", HttpMethod.POST, requestHttpEntity, B.class);
  response = responseEntity.getBody();
} catch (Exception e) {
  return null;
}

解决方案

以下是几种无需修改POJO即可实现忽略null/空值元素的方案:

方案1:配置Jaxb2Marshaller扩展属性(适用于JAXB RI实现)

JAXB RI(GlassFish官方实现)提供了扩展属性com.sun.xml.bind.marshaller.omit-empty-element,设置为true可忽略null或空值元素。通过自定义Jaxb2Marshaller并替换RestTemplate的默认消息转换器实现:

// 1. 创建自定义Jaxb2Marshaller
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(XYZ.class, B.class); // 绑定需要序列化的POJO类

// 2. 设置忽略空值的扩展属性
marshaller.setMarshallerProperties(Map.of(
    "com.sun.xml.bind.marshaller.omit-empty-element", true
));

// 3. 创建并配置消息转换器
Jaxb2RootElementHttpMessageConverter converter = new Jaxb2RootElementHttpMessageConverter();
converter.setMarshaller(marshaller);
converter.setUnmarshaller(marshaller);

// 4. 替换RestTemplate的默认JAXB消息转换器
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().removeIf(c -> c instanceof Jaxb2RootElementHttpMessageConverter);
restTemplate.getMessageConverters().add(converter);

如果项目使用EclipseLink MOXy作为JAXB实现,可通过外部XML映射文件配置忽略null值,无需修改POJO:

步骤1:引入MOXy依赖(若未引入)

<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>org.eclipse.persistence.moxy</artifactId>
    <version>匹配你的Spring版本</version>
</dependency>

步骤2:创建外部映射文件(如jaxb-moxy.xml)

<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
               package-name="你的POJO所在包路径">
    <java-types>
        <java-type name="XYZ">
            <java-attributes>
                <!-- nullable="false" 表示属性为null时不序列化该元素 -->
                <xml-element java-attribute="a" name="A" nullable="false"/>
                <xml-element java-attribute="b" name="B" nullable="false"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>

步骤3:配置MOXy Marshaller到RestTemplate

MoxyMarshaller marshaller = new MoxyMarshaller();
marshaller.setContextPaths("你的POJO所在包路径");
marshaller.setMappingResources("jaxb-moxy.xml"); // 指定外部映射文件

Jaxb2RootElementHttpMessageConverter converter = new Jaxb2RootElementHttpMessageConverter();
converter.setMarshaller(marshaller);
converter.setUnmarshaller(marshaller);

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().removeIf(c -> c instanceof Jaxb2RootElementHttpMessageConverter);
restTemplate.getMessageConverters().add(converter);

方案3:切换为Jackson XML序列化(灵活通用)

使用Jackson的XML序列化模块,通过配置即可忽略null值,无需依赖JAXB特定实现:

步骤1:引入Jackson XML依赖

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>匹配你的Spring版本</version>
</dependency>

步骤2:配置XmlMapper并替换消息转换器

// 1. 配置XmlMapper,忽略null值并开启根节点包裹(适配@XmlRootElement)
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略null值属性
xmlMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true); // 包裹根节点

// 2. 创建Jackson XML消息转换器
MappingJackson2XmlHttpMessageConverter converter = new MappingJackson2XmlHttpMessageConverter(xmlMapper);

// 3. 替换RestTemplate的默认消息转换器
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().removeIf(c -> c instanceof Jaxb2RootElementHttpMessageConverter);
restTemplate.getMessageConverters().add(converter);

注意事项

  • 确认项目使用的JAXB实现:优先匹配对应方案(JAXB RI用方案1,MOXy用方案2);若无特殊依赖,方案3的Jackson XML配置更通用。
  • 升级依赖后,原默认消息转换器的配置可能被重置,需确保自定义转换器被正确加载。

内容的提问来源于stack exchange,提问作者Ondrej Havlicek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:57:10