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

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

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

但是我得到的生成方法返回Boolean ,而我想要boolean

这是复杂的类型:

         

生成的类看起来像这样:

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

问题是虽然装箱会起作用,但如果提供的XML不包含pricepoint_custom_fields_required的值,则类的布尔字段为空,而不是false。 这样做的时候我得到NullPointerExceptions

 methodWhichTakesPrimitiveBooleanArg(myUsageAuthRateChargeInstance.isPricepointCustomFieldsRequired()); 

因为它试图取消传入的布尔值 – 除了它为空。

我无法更改架构,我无法调整所有客户端代码来进行空检查。

我在binding.xml中设置了optionalProperty属性,如下所示:

  

在规范中,它说:“如果属性的值是”原始的“,它会像在JAXB 1.0中那样绑定”

然而,这显然没有发生。

我怎么解决这个问题?

更新:

这现在在jaxb 2.2.9中修复: https ://java.net/jira/browse/JAXB/fixforversion/16850

问题

你得到Boolean而不是boolean的原因是你的元素定义中有minOccurs="0" 。 将为缺席元素存储null值。

  

解决方案应该是什么

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

     

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

 xjc -b binding.xml my-schema.xsd 

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

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

解决方法

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

binding.xml

        

UsageAuthRateCharge

根据需要使用方法创建此类。

XJC电话

在XJC调用上使用-b标志来指定binding.xml文件

 xjc -b binding.xml my-schema.xsd 

UPDATE

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

我是EclipseLink JAXB(MOXy)的领导者。 我已经联系了执行JAXB参考实现的同事(他们也适用于Oracle)。 以下是我从他们那里得到的答复:

我已经在trunk中测试了 – 问题就存在了。 我会检查代码修复它有多容易。

希望你能够真正解决这个问题。

尝试这个…

         

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

我厌倦了等待开发团队的修复,所以我卷起袖子自己做了。

我将下面的代码包含在内,以帮助那些也是问题的人。

免责声明 :我的代码可能不是解决问题的最佳方法,但它对我有用。

生成的代码现在看起来像这样:

 public boolean isPricepointCustomFieldsRequired() { if (pricepointCustomFieldsRequired == null) { return false; } else { return pricepointCustomFieldsRequired; } } 

修改如下:

com.sun.tools.xjc.reader.xmlschema.bindinfo.BIProperty:createElementProperty,line~358

行后

  types.addTo(丙); 

插入以下代码:

 if (prop.isOptionalPrimitive() && getOptionalPropertyMode() == OptionalPropertyMode.PRIMITIVE && !prop.getTypes().isEmpty() && "boolean".equals(prop.getTypes().get(0).getTypeName().getLocalPart()) ) { prop.defaultValue= CDefaultValue.create(CBuiltinLeafInfo.BOOLEAN, new XmlString("false")); } 

只是为了完成它

 type="xs:boolean" minOccurs="0" maxOccurs="1" == Boolean value (object) type="xs:boolean" minOccurs="0" maxOccurs="1" nillable="true" == JAXBElement value (object) type="xs:boolean" minOccurs="1" maxOccurs="1" == boolean value (primitive) type="xs:boolean" minOccurs="1" maxOccurs="1" nillable="true" == Boolean value (object)