Note:我是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-generate.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.*;
Root
下面是一个示例域类,其中包含一些String
字段。自从XmlAdapter
已在包级别注册,它将应用于该包中的所有映射字符串字段/属性。
package forum11894193;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
String a;
String b;
String c;
}
Demo
在下面的演示代码中,我们将创建一个实例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>