如何通过JAXB绑定将XSD空复杂类型TextType替换为String类型?
问题描述
必须使用一份不可修改的WSDL,其中定义了无任何元素的复杂类型TextType,但该类型实际应作为简单String类型使用(仅在单独文档中有说明):
<xs:complexType name="TextType"> </xs:complexType>
TextType在XSD中被用于AnschriftType:
<xs:complexType name="AnschriftType"> <xs:element name="Strasse" type="TextType"/> </xs:complexType>
JAXB默认生成的POJO中,AnschriftType的strasse字段类型为TextType(空类),希望将其替换为java.lang.String,但尝试两种绑定方式均失败:
尝试方案1:指定class和implClass
<jaxb:bindings node="xs:complexType[@name='TextType']"> <jaxb:class name="String" implClass="java.lang.String"/> </jaxb:bindings>
生成的AnschriftType出现错误:getter返回自定义包下的String类,而非java.lang.String:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "AnschriftType" propOrder={...}) public class AnschriftType { @XmlElement(name = "Strasse", type = java.lang.String.class) protected java.lang.String strasse; public package.of.xsd.String getStrasse() { return strasse; } public void setStrasse(package.of.xsd.String value) { this.strasse = ((java.lang.String) value); } }
尝试方案2:指定property的baseType
<jaxb:bindings node="xs:complexType[@name='TextType']"> <jaxb:property> <jaxb:baseType name="java.lang.String"/> </jaxb:property> </jaxb:bindings>
生成的POJO无变化,仍使用TextType作为字段类型。
解决方案
要让JAXB直接将TextType映射为java.lang.String,需要结合引用已有类和XML适配器处理空复杂类型与简单字符串的转换,具体步骤如下:
1. 编写XML适配器类
创建适配器类,用于在XML文本内容和String之间做透传转换(因TextType是空复杂类型,实际XML中对应简单文本节点):
package com.yourpackage; import javax.xml.bind.annotation.adapters.XmlAdapter; public class TextTypeAdapter extends XmlAdapter<String, String> { @Override public String unmarshal(String v) throws Exception { return v; } @Override public String marshal(String v) throws Exception { return v; } }
2. 配置JAXB绑定文件
创建绑定文件(如bindings.xjb),指定TextType引用java.lang.String并使用上述适配器:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0"> <!-- 将TextType直接映射为java.lang.String,使用适配器处理XML转换 --> <jaxb:bindings node="xs:complexType[@name='TextType']"> <jaxb:class ref="java.lang.String"/> <jaxb:javaType adapter="com.yourpackage.TextTypeAdapter" name="java.lang.String"/> </jaxb:bindings> <!-- 确保使用TextType的字段也映射为String --> <jaxb:bindings node="xs:complexType[@name='AnschriftType']/xs:element[@name='Strasse']"> <jaxb:property> <jaxb:baseType name="java.lang.String"/> </jaxb:property> </jaxb:bindings> </jaxb:bindings>
3. 生成POJO
使用xjc命令并指定绑定文件生成代码:
xjc -b bindings.xjb your-schema.xsd
生成的AnschriftType会直接使用String类型:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "AnschriftType", propOrder = { "strasse" }) public class AnschriftType { @XmlElement(name = "Strasse", required = true, type = String.class) @XmlJavaTypeAdapter(TextTypeAdapter.class) protected String strasse; public String getStrasse() { return strasse; } public void setStrasse(String value) { this.strasse = value; } }
失败原因说明
- 方案1中
name="String"会让JAXB在当前包下生成新的String类,而非引用java.lang.String,需改用ref属性指定已有类。 - 方案2的
jaxb:property绑定仅针对属性,无法修改复杂类型本身的映射逻辑,因此无法生效。
内容的提问来源于stack exchange,提问作者Chris Brown
相关产品推荐
相关产品推荐

