你能改变JAXB中nillable属性的默认值吗?

时间:2012-01-12 19:38:51

标签: java jaxb

我正在重构一些代码以使用JAXB和反射将代码输出到客户端,它当前正在使用XMLWriter并每次手动创建标记。

我遇到的问题是,由于客户端的约束,我需要在XML中为空类中的空元素提供java类中的空字段。

虽然我意识到可以通过向每个JAXB nillable=true注释添加XmlElement来解决这个问题,但这并不是最实用的,因为我有很多这样的注释。

我希望找到一种方法将nillable=true设置为全局属性(或默认值)。这也可以使未来的同事更容易处理它,因为他们不需要记住每个注释都应该包含nillable属性。

除了默认行为的描述之外,我没有找到太多内容。我发现令人惊讶的是,过去没有其他人发布过类似的问题。根据我的发现,我认为没有任何内置支持可以使默认配置。这可能是通过自定义JAXB实现或第三方JAXB实现解决的吗?

1 个答案:

答案 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>