JAXB:在特殊值的情况下忽略元素序列化(例如“null”或“Double.NaN”)

JAXB: ignore element serialization in case of special value (e.g. `null` or `Double.NaN`)

我想用 JAXB 序列化一个 Java 对象。该对象具有可能具有特殊值的实例变量,例如null 或另一种情况 Double.NaN.

如果实例变量有这个特殊值,我如何才能只忽略它?

这可能吗?


MWE

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MyClass {

   private double value;
   private Object object;

   public void setValue(double value){this.value = value;}
   public double getValue(){return value;}

   public void setObject(Object object){this.object = object;}
   public Object getObject(){return object;}

}

所以如果 valueDouble.NaNobject 不是 null 我想得到

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MyClass>
  <object>
    ...
  </object>
</MyClass>

在另一种情况下,如果 value 不是 Double.NaN 并且 objectnull 我想得到

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MyClass>
  <value>1.0</value>
</MyClass>

默认情况下不会生成空值 XML,因此您对 object 属性 的要求已得到处理。

对于特殊的double值,创建一个专门的方法来产生XMLvalue值,并抑制value或[=17的法线贴图=] 到 XML.

这可以通过使用 @XmlTransient, or by disabling automatic property selection using XmlAccessType.NONE 进行注释来完成,因此只有注释的属性会映射到 XML。

这是使用第二种方法的示例:

@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class MyClass {

    private double value;
    private Foo foo;

    public MyClass() {
    }
    public MyClass(double value, Foo foo) {
        this.value = value;
        this.foo = foo;
    }

    public void setValue(double value){this.value = value;}
    public double getValue(){return this.value;}

    public void setFoo(Foo foo){this.foo = foo;}
    @XmlElement() public Foo getFoo(){return this.foo;}

    @XmlElement(name = "value")
    public Double getXmlValue() {
        if (Double.isFinite(this.value))
            return this.value;
        return null;
    }
}

public class Foo {
    @XmlElement()
    public String getBar() { return "Test"; }
}

测试

JAXBContext jaxbContext = JAXBContext.newInstance(MyClass.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

marshaller.marshal(new MyClass(Math.PI, null), System.out);
marshaller.marshal(new MyClass(Double.NaN, new Foo()), System.out);

输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<myClass>
    <value>3.141592653589793</value>
</myClass>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<myClass>
    <foo>
        <bar>Test</bar>
    </foo>
</myClass>

注意第一个中缺少 <foo>,因为它是 null,第二个中缺少 <value>,因为 NaN 值为作为 null 值返回。

正常使用 MyClass 在调用 getValue() 时仍会得到 NaN 值。