我们长期以来一直在使用 jaxb 将 XML 解组为我们可以在我们的系统中使用的 POJO。但是,直到最近我才发现 jaxb 如何解析 xml 提供的数据的问题,我想通过实现自定义 XmlAdapter 并强制 jaxb 使用它来覆盖该行为。
假设我们的 xsd 中有一个如下所示的复杂字段定义:
<xs:complexType name="ratingType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="scheme" use="required" type="xs:NMTOKEN"/>
<xs:attribute name="subRatings" use="optional">
<xs:simpleType>
<xs:list itemType='xs:string'/>
</xs:simpleType>
</xs:attribute>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
不做任何改动,jaxb创建如下java类属性:
@XmlAttribute(name = "subRatings")
protected List<String>subRatings;
这通常没问题,但是,由于新的客户要求,我们在该字段上获得的数据将发生变化。
当前用例:
<rating scheme="urn:ncs" subRatings="Violence">MA15+</rating>
这变成了 subRatings=["Violence"],这很棒。
新用例:
<rating scheme="urn:ncs" subRatings="Coarse Language">MA15+</rating>
然而,这会变成 subRatings=["Coarse", "Language"],这是不正确的,并且会导致下游出现问题,因为这不是公认的 subRating。我希望它是 subRatings=["Coarse Language"] 。
我尝试了一些东西,但到目前为止,让我最接近我想要的是使用如下的 jaxb 绑定:
<jxb:bindings schemaLocation="media.xsd" node="//xs:complexType[@name='ratingType']">
<jxb:bindings node=".//xs:attribute[@name='subRatings']">
<jxb:property>
<jxb:baseType>
<xjc:javaType name="java.util.List<String>" adapter="org.jvnet.jaxb2_commons.xml.bind.annotation.adapters.CommaDelimitedStringAdapter"/>
</jxb:baseType>
</jxb:property>
</jxb:bindings>
</jxb:bindings>
生成的类有如下属性定义:
@XmlAttribute(name = "subRatings")
@XmlJavaTypeAdapter(CommaDelimitedStringAdapter.class)
protected List<String>subRatings;
到目前为止一切都很好。但是,出于某种原因,jaxb 将此导入添加到类中:
import java.util.List<String>;
导致它无法编译。
我尝试的另一件事是删除 javaType 名称定义中的特定类型,例如
java.util.List
,但这会导致 jaxb 创建具有原始类型的字段,例如 protected List subRatings;
,这不仅丑陋,而且会像现在任何人一样导致下游问题使用此类需要强制转换子评级对象,使代码有异味。任何想法如何克服这个?请记住,我无法修改生成的类,因为它们是在编译时构建的。