JAXB 编译器将 xs:boolean 绑定到 Java 布尔包装类,而不是布尔基本类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13035975/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JAXB compiler is binding xs:boolean to Java Boolean wrapper class, instead of boolean primitive type
提问by mdarwin
I'm migrating a project from JAXB 1.0 to JAXB 2.1 and I'm having problems with the datatype mapping.
我正在将一个项目从 JAXB 1.0 迁移到 JAXB 2.1,但我在数据类型映射方面遇到了问题。
I'm using the Ant xjcbinding compiler, and I've successfully configured the global bindings such that (for example) xs:datemaps to java.util.Calendar.
我正在使用 Ant xjc绑定编译器,并且我已经成功地配置了全局绑定,这样(例如)xs:date映射到java.util.Calendar。
However I'm getting generated methods which return Boolean
, whereas I want boolean
.
但是,我得到了返回的生成方法Boolean
,而我想要boolean
.
Here is the complex type:
这是复杂类型:
<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>
And the generated class looks like this:
生成的类如下所示:
public class UsageAuthRateCharge {
........
public Boolean isPricepointCustomFieldsRequired() {
return pricepointCustomFieldsRequired;
}
The problem is that although boxing will work, if the supplied XML doesn't contain a value for pricepoint_custom_fields_required
, the class's Boolean field is null, instead of false. So I get NullPointerExceptionswhen doing something like this:
问题是,尽管装箱可以工作,但如果提供的 XML 不包含 的值pricepoint_custom_fields_required
,则该类的布尔字段为 null,而不是 false。所以我在做这样的事情时得到NullPointerExceptions:
methodWhichTakesPrimitiveBooleanArg(myUsageAuthRateChargeInstance.isPricepointCustomFieldsRequired());
because it tries to unbox the Boolean passed in - except it's null.
因为它试图将传入的布尔值拆箱 - 除了它是空值。
I can't change the schema, and I can't adjust all the client code to do the null checks.
我无法更改架构,也无法调整所有客户端代码来执行空检查。
I've set the optionalPropertyattribute in my binding.xmlas follows:
我在binding.xml 中设置了optionalProperty属性,如下所示:
<globalBindings optionalProperty="primitive">
In the spec, it says: "If the attribute's value is "primitive", it binds as it did in JAXB 1.0"
在规范中,它说:“如果属性的值是“原始的”,它会像在 JAXB 1.0 中那样绑定”
Yet this is clearly not happening.
然而,这显然不会发生。
How can I solve this problem?
我怎么解决这个问题?
UPDATE:
更新:
This is now fixed in jaxb 2.2.9: https://java.net/jira/browse/JAXB/fixforversion/16850
这现在在 jaxb 2.2.9 中得到修复:https://java.net/jira/browse/JAXB/fixforversion/16850
采纳答案by mdarwin
I got bored of waiting for a fix from the dev team so I rolled up my sleeves and did it myself.
我厌倦了等待开发团队的修复,所以我卷起袖子自己做。
I'm including the code below to help people for whom this is also an issue.
我包含下面的代码来帮助那些也是一个问题的人。
Disclaimer: my code probably isn't the best way to solve the problem but it works for me.
免责声明:我的代码可能不是解决问题的最佳方法,但它对我有用。
The generated code now looks like this:
生成的代码现在看起来像这样:
public boolean isPricepointCustomFieldsRequired() {
if (pricepointCustomFieldsRequired == null) {
return false;
} else {
return pricepointCustomFieldsRequired;
}
}
And the modification is as follows:
修改如下:
com.sun.tools.xjc.reader.xmlschema.bindinfo.BIProperty:createElementProperty, line ~358
com.sun.tools.xjc.reader.xmlschema.bindinfo.BIProperty:createElementProperty,第 358 行
After the line
线后
types.addTo(prop);
insert the following code:
插入以下代码:
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"));
}
回答by bdoughan
Problem
问题
The reason you are getting Boolean
instead of boolean
is that you have minOccurs="0"
in your element definition. A null
value will be stored for an absent element.
你得到的原因Boolean
,而不是boolean
是,你必须minOccurs="0"
在你的元素定义。null
将为不存在的元素存储一个值。
<xs:element name="pricepoint_custom_fields_required" type="xs:boolean" minOccurs="0"/>
What the Solution Should Be
解决方案应该是什么
The solution should be an external binding file that indicates that a primitive type should be used for optional values (see section 7.5.1 of the JAXB 2.2 specification).
解决方案应该是一个外部绑定文件,它指示一个原始类型应该用于可选值(参见 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>
The external binding file is specified using the -b
option with XJC.
使用-b
带有 XJC的选项指定外部绑定文件。
xjc -b binding.xml my-schema.xsd
Why That Solution Does Not Work
为什么该解决方案不起作用
The following bugs have been opened to track the issue with optionalProperty="primitive"
.
已打开以下错误以跟踪optionalProperty="primitive"
.
Workaround
解决方法
If you don't like the way a class is generated in JAXB, then you can create a class yourself and have JAXB pull it in as part of the schema to class generation.
如果您不喜欢在 JAXB 中生成类的方式,那么您可以自己创建一个类,并让 JAXB 将其作为模式的一部分引入到类生成中。
binding.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
UsageAuthRateCharge
Create this class with the methods as you want them.
使用您想要的方法创建此类。
XJC Call
XJC呼叫
Use the -b
flag on the XJC call to specify the binding.xml
file
使用-b
XJC 调用上的标志来指定binding.xml
文件
xjc -b binding.xml my-schema.xsd
UPDATE
更新
What I was really hoping was that one of the readers might be a jaxb dev team member who could do the change easily in jaxb. User archenroot offered a possible solution in his comments on jaxb issue 927 (a duplicate of 926) which leads me to think that for the right person, it would be a simple job to fix jaxb
我真正希望的是其中一位读者可能是 jaxb 开发团队成员,他可以在 jaxb 中轻松进行更改。用户 archenroot 在他对 jaxb 问题 927(926 的副本)的评论中提供了一个可能的解决方案,这让我认为对于合适的人来说,修复 jaxb 将是一项简单的工作
I'm the EclipseLink JAXB (MOXy)lead. I have reached out to my colleagues who do the JAXB reference implementation (they also work for Oracle). Below is the reply I got from them:
我是EclipseLink JAXB (MOXy) 的负责人。我已经联系了我做 JAXB 参考实现的同事(他们也为 Oracle 工作)。以下是我从他们那里得到的答复:
I've tested in trunk - and the problem exists. I'll check code how easy is to fix it.
我已经在后备箱中测试过 - 问题存在。我会检查代码修复它有多容易。
Hopefully you will be able to get a real fix for this issue.
希望您能够真正解决此问题。
回答by twindham
Try this...
试试这个...
<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>
I found your question as I was looking how to do the exact opposite thing you were doing. I had a boolean attribute that would only generate code that had the attribute as a primitive boolean value. To make jaxb generate this attribute as a Boolean object instead of a boolean primitive, I just removed the use="required" portion of my attribute's definition in the xsd.
我发现了你的问题,因为我正在寻找如何做与你正在做的完全相反的事情。我有一个布尔属性,它只会生成将该属性作为原始布尔值的代码。为了让 jaxb 将此属性生成为布尔对象而不是布尔原语,我只是删除了 xsd 中属性定义的 use="required" 部分。
回答by Martin ?voňava
Just to make it complete
只为让它完整
type="xs:boolean" minOccurs="0" maxOccurs="1" == Boolean value (object)
type="xs:boolean" minOccurs="0" maxOccurs="1" nillable="true" == JAXBElement<Boolean> value (object)
type="xs:boolean" minOccurs="1" maxOccurs="1" == boolean value (primitive)
type="xs:boolean" minOccurs="1" maxOccurs="1" nillable="true" == Boolean value (object)