JAXB (JSR-222) 実装は、 の設定にnull
基づいて、存在しないノードまたは nillable 要素として表すことができます。両方をサポートする必要がある場合、または 2 つを区別する必要がある場合は、.nillable
@XmlElement
JAXBElement
Java モデル
根
型のフィールド/プロパティは、注釈JAXBElement
でマップされます。@XmlElementRef
これは、 で@XmlElementDecl
注釈が付けられたクラスの注釈に対応し@XmlRegistry
ます。
import java.math.BigDecimal;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlElementRef(name="foo")
JAXBElement<BigDecimal> foo;
@XmlElementRef(name="bar")
JAXBElement<BigDecimal> bar;
@XmlElementRef(name="baz")
JAXBElement<BigDecimal> baz;
}
ObjectFactory
import java.math.BigDecimal;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
@XmlElementDecl(name = "foo")
public JAXBElement<BigDecimal> createFoo(BigDecimal value) {
return new JAXBElement<BigDecimal>(new QName("foo"), BigDecimal.class, value);
}
@XmlElementDecl(name = "bar")
public JAXBElement<BigDecimal> createBar(BigDecimal value) {
return new JAXBElement<BigDecimal>(new QName("bar"), BigDecimal.class, value);
}
@XmlElementDecl(name = "baz")
public JAXBElement<BigDecimal> createBaz(BigDecimal value) {
return new JAXBElement<BigDecimal>(new QName("baz"), BigDecimal.class, value);
}
}
デモコード
入力.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<baz>123.456</baz>
</root>
デモ
以下は、すべてが機能することを示すために実行できるデモ コードです。を使用して、必要に応じJAXBIntrospector
て をアンラップして実際の値を取得する方法に注意してください。JAXBElement
import java.io.File;
import java.math.BigDecimal;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class, ObjectFactory.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum18440987/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
nullOrAbsent("foo", root.foo);
nullOrAbsent("bar", root.bar);
nullOrAbsent("baz", root.baz);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
private static void nullOrAbsent(String property, JAXBElement<BigDecimal> value) {
System.out.print(property);
if(null == value) {
System.out.print(": ABSENT - ");
} else if(value.isNil()) {
System.out.print(": NIL - ");
} else {
System.out.print(": VALUE - ");
}
System.out.println(JAXBIntrospector.getValue(value));
}
}
出力
foo: ABSENT - null
bar: NIL - null
baz: VALUE - 123.456
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<baz>123.456</baz>
</root>
アップデート
既存の get/set メソッドを維持したい場合は、この回答にあるようにフィールド アクセスを維持し、アクセサ メソッドを次のように変更できます。
public BigDecimal getBar() {
if(null == bar) {
return null;
}
return bar.getValue();
}
public void setBar(BigDecimal bar) {
if(null == this.bar) {
this.bar = new JAXBElement<BigDecimal>(new QName("bar"), BigDecimal.class, bar);
} else {
this.bar.setValue(bar);
}
}
isSet
さらに、値が設定されているかどうかを確認するメソッドを追加できます。
public boolean isSetBar() {
return null != bar;
}
この方法では、にアクセスできる必要はありませんUnmarshaller
。が確実にObjectFactory
取得されるようにするには、アノテーションを使用し@XmlSeeAlso
てドメイン クラスの 1 つから参照します。
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso(ObjectFactory.class)
public class Root {