JAXB 编译器将 xs:boolean 绑定到 Java Boolean 包装器类,而不是布尔基元类型

2022-09-02 12:28:37

我正在将一个项目从 JAXB 1.0 迁移到 JAXB 2.1,但我在数据类型映射方面遇到了问题。

我正在使用Ant xjc绑定编译器,并且我已经成功配置了全局绑定,例如,xs:date映射到java.util.Calendar

但是,我得到的是返回,而我想要.Booleanboolean

下面是复杂类型:

<xs:element name="usage-auth-rate-charge">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="service-id" type="xs:string"/>
            <xs:element name="pricepoint_custom_fields_required" type="xs:boolean" minOccurs="0"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

生成的类如下所示:

public class UsageAuthRateCharge {
........
public Boolean isPricepointCustomFieldsRequired() {
    return pricepointCustomFieldsRequired;
}

问题在于,尽管装箱可以正常工作,但如果提供的 XML 不包含 的值,则该类的布尔字段为 null,而不是 false。因此,在执行以下操作时,我得到了NullPointerExceptionspricepoint_custom_fields_required

methodWhichTakesPrimitiveBooleanArg(myUsageAuthRateChargeInstance.isPricepointCustomFieldsRequired());

因为它试图取消包装传入的布尔值 - 除了它是空的。


我无法更改架构,也无法调整所有客户端代码以执行 null 检查。

我已经在绑定中设置了可选的Property属性.xml如下所示:

<globalBindings optionalProperty="primitive">

在规范中,它说:“如果属性的值为'基元',它将像在JAXB 1.0中那样绑定”

然而,这显然没有发生。

我该如何解决这个问题?

更新:

现在在 jaxb 2.2.9 中修复了此问题:https://java.net/jira/browse/JAXB/fixforversion/16850


答案 1

问题

你得到而不是的原因是你的元素定义。将为缺少的元素存储一个值。BooleanbooleanminOccurs="0"null

<xs:element name="pricepoint_custom_fields_required" type="xs:boolean" minOccurs="0"/>

解决方案应该是什么

解决方案应该是一个外部绑定文件,该文件指示应将基元类型用于可选值(请参见 JAXB 2.2 规范的第 7.5.1 节)。

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">
    <jaxb:globalBindings optionalProperty="primitive"/>
</jaxb:bindings>

外部绑定文件是使用带有 XJC 的选项指定的。-b

xjc -b binding.xml my-schema.xsd

为什么该解决方案不起作用

已打开以下错误以跟踪 问题。optionalProperty="primitive"

解决方法

如果您不喜欢在 JAXB 中生成类的方式,那么您可以自己创建一个类,并让 JAXB 将其作为模式到类生成的一部分。

装订.xml

<jxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">

    <jxb:bindings schemaLocation="my-schema.xsd">
        <jxb:bindings node="//xs:element[@name='usage-auth-rate-charge']/complexType">
            <jxb:class ref="com.example.foo.UsageAuthRateCharge"/>
        </jxb:bindings>
    </jxb:bindings>
</jxb:bindings>

UsageAuthRateCharge

使用所需的方法创建此类。

XJC呼叫

使用 XJC 调用上的标志指定文件-bbinding.xml

xjc -b binding.xml my-schema.xsd

更新

我真正希望的是,其中一位读者可能是jaxb开发团队成员,他可以在jaxb中轻松进行更改。用户archenroot在他对jaxb问题927(926的副本)的评论中提供了一个可能的解决方案,这使我认为对于合适的人来说,修复jaxb将是一项简单的工作。

我是EclipseLink JAXB(MOXy)的领导者。我已经联系了做JAXB参考实现的同事(他们也为Oracle工作)。以下是我从他们那里得到的回复:

我已经在主干中进行了测试 - 并且存在问题。我将检查代码修复它的难易程度。

希望您能够获得此问题的真正解决方案。


答案 2

试试这个...

<xs:element name="usage-auth-rate-charge">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="service-id" type="xs:string"/>
        </xs:sequence>
        <xs:attribute name="chosen" type="xs:boolean" use="required"/>
    </xs:complexType>
</xs:element>

当我正在寻找如何做你正在做的事情时,我发现了你的问题。我有一个布尔属性,它只会生成将该属性作为基元布尔值的代码。为了使 jaxb 将此属性生成为布尔对象而不是布尔基元,我只是在 xsd 中删除了属性定义的 use=“required” 部分。


推荐