我正在重构一些代码以使用JAXB和反射将代码输出到客户端,它当前正在使用XMLWriter并每次手动创建标记。
我遇到的问题是,由于客户端的约束,我需要在XML中为空类中的空元素提供java类中的空字段。
虽然我意识到可以通过向每个JAXB nillable=true
注释添加XmlElement
来解决这个问题,但这并不是最实用的,因为我有很多这样的注释。
我希望找到一种方法将nillable=true
设置为全局属性(或默认值)。这也可以使未来的同事更容易处理它,因为他们不需要记住每个注释都应该包含nillable
属性。
除了默认行为的描述之外,我没有找到太多内容。我发现令人惊讶的是,过去没有其他人发布过类似的问题。根据我的发现,我认为没有任何内置支持可以使默认配置。这可能是通过自定义JAXB实现或第三方JAXB实现解决的吗?
答案 0 :(得分:1)
注意:我是 EclipseLink JAXB (MOXy) 负责人,也是JAXB 2 (JSR-222)专家组的成员。
我已经输入了一个增强请求,要将此行为添加到EclipseLink JAXB(MOXy)中:
周围工作
如果解决了所有映射的字符串字段/属性都映射到XML元素的问题,那么以下XmlAdapter方法可能对您有用:
<强> NullStringAdapter 强>
此XmlAdapter
将封送String
的实例作为名为AdaptedString
的对象。 AdaptedString
包含String
值以及映射到xsi:nil
属性的字段。在XmlAdapter
中,我们将根据String
值是否为空来设置该字段的值。
package forum8841221;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;
public class NullStringAdapter extends XmlAdapter<NullStringAdapter.AdaptedString, String> {
@Override
public AdaptedString marshal(String v) throws Exception {
AdaptedString adaptedString = new AdaptedString();
if(null == v) {
adaptedString.nil = true;
}
adaptedString.value = v;
return adaptedString;
}
@Override
public String unmarshal(AdaptedString v) throws Exception {
return v.value;
}
public static class AdaptedString {
@XmlAttribute(namespace="http://www.w3.org/2001/XMLSchema-instance")
public Boolean nil;
@XmlValue
@XmlJavaTypeAdapter(VoidStringAdapter.class)
public String value;
}
public static class VoidStringAdapter extends XmlAdapter<String, String> {
@Override
public String marshal(String v) throws Exception {
return v;
}
@Override
public String unmarshal(String v) throws Exception {
return v;
}
}
}
<强>包信息强>
我们可以通过在包级别注册XmlAdapter
来注册我们希望此String
应用于此包上的所有映射XmlAdapter
字段/属性。
@XmlJavaTypeAdapter(value=NullStringAdapter.class, type=String.class)
@XmlSchema(xmlns={@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")})
package forum8841221;
import javax.xml.bind.annotation.adapters.*;
import javax.xml.bind.annotation.*;
<强>根强>
以下是我用于此示例的域类。它有几个String属性,其中一个用@XmlElement注释(nillable = true)
package forum8841221;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Root {
private String a;
private String b;
private String c;
private String d;
public String getA() {
return a;
}
public void setA(String a) {
this.a = a;
}
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
public String getC() {
return c;
}
public void setC(String c) {
this.c = c;
}
@XmlElement(nillable=true)
public String getD() {
return d;
}
public void setD(String d) {
this.d = d;
}
}
<强>演示强>
package forum8841221;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Root root = new Root();
root.setB("B");
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
<强>输出强>
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<a xsi:nil="true"/>
<b>B</b>
<c xsi:nil="true"/>
<d xsi:nil="true"/>
</root>