如何将包含JAXBElement的SOAP响应对象映射为目标POJO?
解决JAX-WS响应转JSON时的冗余字段问题
你遇到的问题其实很常见——wsimport生成的JAXB类会用JAXBElement包装属性,导致JSON序列化时带出一堆不必要的元数据。不用手动逐个提取值,这几个高效方案可以帮你解决:
方案1:用Jackson的JAXB注解模块自动处理
Jackson提供了专门的模块来识别JAXB注解,能自动解析JAXBElement并提取里面的value值,不用改任何生成的代码。
步骤:
- 引入依赖(Maven为例):
<dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-jaxb-annotations</artifactId> <version>你的Jackson版本</version> </dependency>
- 配置ObjectMapper并注册模块:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; // 初始化ObjectMapper ObjectMapper objectMapper = new ObjectMapper(); JaxbAnnotationModule jaxbModule = new JaxbAnnotationModule(); objectMapper.registerModule(jaxbModule); // 避免空对象序列化报错 objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); // 转换GetUserResponse为JSON String cleanJson = objectMapper.writeValueAsString(getUser(userId));
这样序列化出来的JSON就会自动去掉JAXBElement的冗余字段,只保留实际值。
方案2:调整wsimport生成参数,直接生成普通POJO
从根源解决问题,让wsimport生成不带JAXBElement包装的普通Java类,这样后续转JSON完全不会有冗余字段。
方法:
创建一个JAXB绑定文件(比如jaxb-bindings.xml):
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1"> <jaxb:globalBindings generateElementProperty="false"/> </jaxb:bindings>
然后在执行wsimport时加上-b参数指定这个绑定文件:
wsimport -b jaxb-bindings.xml http://your-service-url?wsdl
或者在Maven的jaxws-maven-plugin里配置绑定文件:
<plugin> <groupId>org.jvnet.jax-ws-commons</groupId> <artifactId>jaxws-maven-plugin</artifactId> <version>2.3</version> <executions> <execution> <goals> <goal>wsimport</goal> </goals> <configuration> <wsdlUrls> <wsdlUrl>http://your-service-url?wsdl</wsdlUrl> </wsdlUrls> <bindingFiles> <bindingFile>src/main/resources/jaxb-bindings.xml</bindingFile> </bindingFiles> </configuration> </execution> </executions> </plugin>
生成的User类里的userId、name等属性会直接是普通类型(比如Integer、String),不再是JAXBElement,转JSON自然就是你想要的简洁格式。
方案3:用对象映射工具(如ModelMapper)转成自定义DTO
如果需要更灵活地控制输出结构(比如重命名字段、过滤某些属性),可以用ModelMapper这类工具自动把JAXB生成的对象映射到自定义的DTO类。
步骤:
- 引入ModelMapper依赖:
<dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>2.4.4</version> </dependency>
- 定义你需要的DTO类:
public class UserDTO { private Integer userId; private String name; private Boolean active; private String postalCode; // 省略getter和setter }
- 自动映射:
ModelMapper modelMapper = new ModelMapper(); // 从JAXB生成的User对象映射到DTO UserDTO userDTO = modelMapper.map(getUser(userId).getUser().getValue(), UserDTO.class); // 转成JSON String json = new ObjectMapper().writeValueAsString(userDTO);
ModelMapper会自动匹配字段名,帮你完成值的提取和映射,不用手动写一堆getter代码。
总结
- 如果能修改代码生成方式,方案2是最优解,从根源避免冗余字段;
- 如果不能改生成的代码,方案1最省心,只需配置Jackson即可;
- 如果需要自定义输出结构,方案3更灵活。
内容的提问来源于stack exchange,提问作者yrazlik
相关产品推荐
相关产品推荐

