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

如何为XSD生成类的List<String>属性添加自定义JAXB XML适配器

解决JAXB解析带空格的list属性问题

问题背景

我们长期使用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>

默认生成的Java属性

未做任何修改时,JAXB生成的对应Java类属性如下:

@XmlAttribute(name = "subRatings")
protected List<String> subRatings;

解析行为异常场景

  • 当前正常场景:
    XML内容:

    <rating scheme="urn:ncs" subRatings="Violence">MA15+</rating>
    

    解析后subRatings=["Violence"],符合预期。

  • 新异常场景:
    XML内容:

    <rating scheme="urn:ncs" subRatings="Coarse Language">MA15+</rating>
    

    JAXB默认按空格拆分list项,解析后subRatings=["Coarse", "Language"],不符合我们需要的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&amp;lt;String&amp;gt;" 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;,不仅不符合规范,还会导致下游使用时需要强制类型转换,代码可读性差。注意:我们无法修改编译时生成的类,必须通过绑定配置解决问题。

解决方案

通过在绑定配置中添加<jxb:genericType>指定泛型参数,同时保持<xjc:javaType>的name为java.util.List,即可生成正确的泛型字段和导入语句。

修改后的绑定配置:

<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" adapter="org.jvnet.jaxb2_commons.xml.bind.annotation.adapters.CommaDelimitedStringAdapter"/>
            </jxb:baseType>
            <jxb:genericType>java.util.List&lt;java.lang.String&gt;</jxb:genericType>
        </jxb:property>
    </jxb:bindings>
</jxb:bindings>

配置说明

  1. <xjc:javaType>指定基础类型为java.util.List,避免生成错误的泛型导入语句;
  2. <jxb:genericType>明确指定泛型参数为java.util.List<java.lang.String>,让JAXB生成带泛型的字段定义;
  3. 使用CommaDelimitedStringAdapter后,JAXB会按逗号拆分subRatings的值,而不是默认的空格,因此"Coarse Language"会被解析为单个List元素,符合业务需求。

生成的正确代码如下:

import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.jvnet.jaxb2_commons.xml.bind.annotation.adapters.CommaDelimitedStringAdapter;

// ... 其他类定义
@XmlAttribute(name = "subRatings")
@XmlJavaTypeAdapter(CommaDelimitedStringAdapter.class)
protected List<String> subRatings;

内容的提问来源于stack exchange,提问作者CjRobin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 04:12:49