如何从SOAP请求消息中获取Integer类型的null对象?
如何将SOAP请求中空的dateOfBirth子字段映射为Java Integer类型的null值
问题场景
作为SOAP技术新手,收到如下SOAP请求片段,其中dateOfBirth下的year、month、day均为空标签:
<patient> <dateOfBirth> <year></year> <month></month> <day></day> </dateOfBirth> <firstName>Ivan</firstName> <lastName>Luku</lastName> </patient>
对应的XSD Schema片段定义如下:
xs:complexType name="personVO"> <xs:complexContent> <xs:extension base="tns:tenantableVO"> <xs:sequence> <xs:element name="dateOfBirth" type="tns:localDateVO"/> <xs:element name="firstName" type="xs:string"/> <xs:element name="lastName" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> ------------------------------------------ <xs:complexType name="localDateVO"> <xs:sequence> <xs:element name="day" type="xs:int" nillable="true" minOccurs="0"/> <xs:element name="month" type="xs:int" nillable="true" minOccurs="0"/> <xs:element name="year" type="xs:int" nillable="true" minOccurs="0"/> </xs:sequence> </xs:complexType>
上述字段在Java代码中为Integer类型,期望接收请求后这些空字段能映射为null值,但之前的尝试遇到了问题:
- 在get方法上添加
@XmlAttribute注解无效,无论字段是否有值都返回null:
@XmlAttribute public Integer getDay() { return day; } @XmlAttribute public Integer getMonth() { return month; } @XmlAttribute public Integer getYear() { return year; }
- 尝试在字段上添加相同注解时,出现Class has two properties of the same name错误。
解决方案
1. 替换注解类型,使用@XmlElement匹配XSD定义
XSD中day、month、year是<xs:sequence>下的子元素,并非XML属性,因此不能使用@XmlAttribute,需改用@XmlElement并配置与XSD一致的属性:
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlType(name = "localDateVO", propOrder = {"day", "month", "year"}) public class LocalDateVO { private Integer day; private Integer month; private Integer year; @XmlElement(nillable = true, required = false) public Integer getDay() { return day; } public void setDay(Integer day) { this.day = day; } @XmlElement(nillable = true, required = false) public Integer getMonth() { return month; } public void setMonth(Integer month) { this.month = month; } @XmlElement(nillable = true, required = false) public Integer getYear() { return year; } public void setYear(Integer year) { this.year = year; } }
nillable=true对应XSD中的nillable="true",required=false对应minOccurs="0",确保JAXB正确识别字段的可空特性。
2. 自定义适配器处理空标签到null的转换
若空标签仍未映射为null(JAXB默认会将空元素解析为空字符串,而Integer类型无法直接转换),可添加自定义适配器:
首先创建适配器类:
import javax.xml.bind.annotation.adapters.XmlAdapter; public class EmptyStringToNullIntegerAdapter extends XmlAdapter<String, Integer> { @Override public Integer unmarshal(String v) throws Exception { if (v == null || v.trim().isEmpty()) { return null; } return Integer.parseInt(v); } @Override public String marshal(Integer v) throws Exception { return v != null ? v.toString() : null; } }
然后在对应的get方法上添加适配器注解:
@XmlElement(nillable = true, required = false) @XmlJavaTypeAdapter(EmptyStringToNullIntegerAdapter.class) public Integer getYear() { return year; } // month和day字段的get方法同理添加该注解
3. 解决重复属性错误
出现Class has two properties of the same name是因为JAXB默认同时识别字段和get/set方法作为属性,导致重复,可通过以下两种方式解决:
- 只在字段上添加注解,并给类添加
@XmlAccessorType(XmlAccessType.FIELD),指定JAXB仅通过字段访问属性:
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "localDateVO", propOrder = {"day", "month", "year"}) public class LocalDateVO { @XmlElement(nillable = true, required = false) private Integer day; @XmlElement(nillable = true, required = false) private Integer month; @XmlElement(nillable = true, required = false) private Integer year; // 保留get/set方法但无需添加注解 public Integer getDay() { return day; } public void setDay(Integer day) { this.day = day; } // 其他get/set方法同理 }
- 或者仅在get方法上添加注解,字段上不添加注解,避免JAXB重复识别。
内容的提问来源于stack exchange,提问作者ivashchenko_ivan
相关产品推荐
相关产品推荐

