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

如何配置Feign/JAXB将空列表序列化为带空内容的标签

解决Feign/JAXB空列表生成自闭合XML标签的问题

当通过Feign调用SOAP服务时,JAXB将空列表序列化为自闭合标签<someName />,要改成成对标签<someName></someName>,可以通过以下几种方式实现:

方法一:配置JAXB Marshaller(基于MOXy实现)

如果使用EclipseLink MOXy作为JAXB实现(需在jaxb.properties中指定javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory),可以在创建Marshaller时设置属性强制生成成对空标签:

Marshaller marshaller = jaxbContext.createMarshaller();
// 开启空元素成对标签生成
marshaller.setProperty("eclipselink.marshal-empty-elements", Boolean.TRUE);

如果是Feign集成场景,可自定义JAXB编码器注入该配置,替换默认编码器。

方法二:自定义XmlAdapter处理空列表

创建适配器类,将空列表转换为非null的空集合,触发JAXB生成成对标签:

import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.util.ArrayList;
import java.util.List;

public class EmptyListAdapter extends XmlAdapter<List<String>, List<String>> {
    @Override
    public List<String> unmarshal(List<String> v) throws Exception {
        return v;
    }

    @Override
    public List<String> marshal(List<String> v) throws Exception {
        return (v == null || v.isEmpty()) ? new ArrayList<>() : v;
    }
}

无需修改生成代码的配置方式

通过JAXB外部绑定文件(binding.xml),在生成代码时自动为目标字段添加适配器:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
    <jaxb:bindings schemaLocation="your-service.wsdl" node="//xs:element[@name='someName']">
        <jaxb:property>
            <jaxb:typeAdapter value="com.your.package.EmptyListAdapter"/>
        </jaxb:property>
    </jaxb:bindings>
</jaxb:bindings>

生成代码时指定该绑定文件(如Maven的maven-jaxb2-plugin添加<bindingDirectory>配置)。

方法三:自定义Feign编码器替换自闭合标签

如果上述方法不生效,可在Feign编码器中手动替换XML内容:

public class CustomJaxbEncoder extends JaxbEncoder {
    public CustomJaxbEncoder(JAXBContext context) {
        super(context);
    }

    @Override
    public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
        try {
            StringWriter writer = new StringWriter();
            getJAXBContext().createMarshaller().marshal(object, writer);
            // 替换自闭合标签为成对标签
            String processedXml = writer.toString().replaceAll("<someName />", "<someName></someName>");
            template.body(processedXml, StandardCharsets.UTF_8);
        } catch (JAXBException e) {
            throw new EncodeException("XML序列化失败", e);
        }
    }
}

然后在Feign客户端配置中注入该编码器:

@Configuration
public class SoapClientConfig {
    @Bean
    public Encoder feignEncoder() throws JAXBException {
        JAXBContext context = JAXBContext.newInstance(YourGeneratedRequestClass.class);
        return new CustomJaxbEncoder(context);
    }
}

内容的提问来源于stack exchange,提问作者Rafał Borkowski

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 01:05:20