区别在于我无法将注释添加到package-
info.java,因为我们的所有JAXB类型都是从每次构建的模式中生成的。如果可能的话,我也更愿意不更改JAXB提供程序。
我想要实现的是设置一个空的String不会创建该元素,但是我需要为从许多模式中生成的所有JAXB类型设置它。有没有办法将其应用于所有生成的JAXB类中的所有String字段?
更新 我已经通过进行以下更改来设法为模式中的所有字符串生成XML适配器:
在项目POM中,我将此添加到了maven-jaxb2-plugin中:
<bindingDirectory>src/main/resources</bindingDirectory>
<bindingIncludes>
<include>bindings.xjb</include>
</bindingIncludes>
这是我的bindings.xjb文件:
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jxb:globalBindings>
<jxb:javaType name="java.lang.String" xmlType="xs:token"
parseMethod="com.project.Formatter.parseString"
printMethod="com.project.Formatter.printString"/>
</jxb:globalBindings>
</jxb:bindings>
以及格式化方法:
public static String printString(final String value)
{
if (StringUtils.isBlank(value))
{
return null;
}
return value;
}
问题在于这会导致JAXB内的Null指针异常。这是堆栈跟踪:
Caused by: java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.output.SAXOutput.text(SAXOutput.java:158)
at com.sun.xml.bind.v2.runtime.XMLSerializer.leafElement(XMLSerializer.java:321)
at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$1.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:210)
at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$1.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:209)
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.writeLeafElement(TransducedAccessor.java:250)
at com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:98)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.ArrayElementNodeProperty.serializeItem(ArrayElementNodeProperty.java:65)
at com.sun.xml.bind.v2.runtime.property.ArrayElementProperty.serializeListBody(ArrayElementProperty.java:168)
at com.sun.xml.bind.v2.runtime.property.ArrayERProperty.serializeBody(ArrayERProperty.java:152)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:322)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:681)
at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:150)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:156)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl$1.serializeBody(ElementBeanInfoImpl.java:185)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeBody(ElementBeanInfoImpl.java:305)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:312)
at com.sun.xml.bind.v2.runtime.ElementBeanInfoImpl.serializeRoot(ElementBeanInfoImpl.java:71)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:490)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:328)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:257)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:103)
此问题的原因归结为此方法:
com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor.CompositeTransducedAccessorImpl.hasValue(BeanT)
如果在运行任何适配器 之前 该值不为null , 则上述方法将呈现该元素。
是否有任何方法可以覆盖JAXB中使用的访问器,以便在确定是否呈现元素之前运行适配器?还有另一种方法可以实现我想要的吗?
注意: 我是 EclipseLink
JAXB(MOXy)的
负责人,并且是
JAXB(JSR-222)
专家组的成员。
您所做的正确,您看到的错误是由于我认为是 JAXB参考实现中 的错误所致。JAXB
RI应该能够处理从中返回的空值XmlAdapter
。该用例适用于EclipseLink JAXB(MOXy),下面将通过示例进行演示。
字符串适配器
下面是一个实现,它近似于从XML模式生成Java模型后所得到的实现(请参阅http://blog.bdoughan.com/2011/08/xml-
schema-to-java-generating。 html)。
package forum11894193;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class StringAdapter extends XmlAdapter<String, String> {
@Override
public String marshal(String string) throws Exception {
if("".equals(string)) {
return null;
}
return string;
}
@Override
public String unmarshal(String string) throws Exception {
return string;
}
}
包装信息
由于您正在注册全局适配器,因此将从package- info
类似以下类的类中进行引用(请参阅:http : //blog.bdoughan.com/2012/02/jaxb-and-
package-level-xmladapters.html)。
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
})
package forum11894193;
import javax.xml.bind.annotation.adapters.*;
根
下面是带有几个String
字段的示例域类。由于XmlAdapter
已在包级别注册,因此它将应用于该包中的所有映射的String字段/属性。
package forum11894193;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
String a;
String b;
String c;
}
演示版
在下面的演示代码中,我们将创建一个实例,Root
将几个字段设置为""
,然后将其编组为XML。
package forum11894193;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Root root = new Root();
root.a = "";
root.b = "b";
root.c = "";
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
使用JAXB RI输出
在此示例中使用JAXB RI会产生NPE。堆栈跟踪是不同的,但是我们最有可能使用不同的封送方法。我还使用了JDK中包含的JAXB
RI版本,该版本已重新打包为com.sun.xml.internal.bind.v2
。
Exception in thread "main" java.lang.NullPointerException
at com.sun.xml.internal.bind.v2.runtime.output.Encoded.setEscape(Encoded.java:96)
at com.sun.xml.internal.bind.v2.runtime.output.UTF8XmlOutput.doText(UTF8XmlOutput.java:294)
at com.sun.xml.internal.bind.v2.runtime.output.UTF8XmlOutput.text(UTF8XmlOutput.java:283)
at com.sun.xml.internal.bind.v2.runtime.output.IndentingUTF8XmlOutput.text(IndentingUTF8XmlOutput.java:141)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.leafElement(XMLSerializer.java:293)
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$1.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:179)
at com.sun.xml.internal.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$1.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:166)
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.writeLeafElement(TransducedAccessor.java:239)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:87)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:306)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:561)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:290)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:462)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:314)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:243)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:75)
at forum11894193.Demo.main(Demo.java:17)
使用EclipseLink JAXB(MOXy)输出
当MOXy用作JAXB提供程序时,您将获得所需的输出。有关将MOXy指定为JAXB提供程序的信息,请参见:http ://blog.bdoughan.com/2011/05/specifying-
eclipselink-moxy-as-your.html 。
<?xml version="1.0" encoding="UTF-8"?>
<root>
<b>b</b>
</root>
我的问题非常类似于当字符串为空但不为null时如何防止在JAXB中编组空标记 区别在于我无法将注释添加到包信息。java作为我们所有的JAXB类型都是从每个构建的模式中生成的。如果可能的话,我也不希望更改JAXB提供程序。 我想要实现的是,设置空字符串不会创建元素,但我需要为许多模式中生成的所有JAXB类型设置此值。有没有办法将其应用于所有生成的JAXB类中的所有字符串字段? 更新我已通过以下更改
问题解决 将XmlElementRef注释更改为@XmlElementRef(name=“Option”,type=Option.class,required=false)后,将@XmlRootElement(name=“Option”)添加到选项中。班 更新: 根据laune的建议,我添加了两个类(Options和Option),并修改了GuimopProperties类,如下所示 但当我必须新
问题内容: 我有以下类,它是由Jackson映射的(简化版): 在某些情况下,服务器会返回,然后我想将name设置为空的Java String。 是否有任何Jackson注释,或者如果属性为,我应该只检查getter中的null并返回空字符串? 问题答案: 您可以在默认构造函数中或声明时进行设置: 要么
我有以下由Jackson映射的类(简化版): 在某些情况下,服务器返回,然后我想将name设置为空Java字符串。 是否有任何Jackson注释,或者如果属性为,我应该只检查getter中的null并返回空字符串吗?
问题内容: 是否可以通过SQL语句确保列的默认值为空字符串而不是? 问题答案: 是-使用DEFAULT约束:
本文向大家介绍Java判断字符串为空、字符串是否为数字,包括了Java判断字符串为空、字符串是否为数字的使用技巧和注意事项,需要的朋友参考一下 关于 String 的判空: 注:“==”比较两个变量本身的值,即两个对象在内存中的首地址。而“equals()”比较字符串中所包含的内容是否相同。第二种写法中,一旦 selection 真的为 null,则在执行 equals 方法的时候会直接报空指针异