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)