Convert nil="true" to null during unmarshal operation

java, jaxb, jaxb2, xml, xml-nil

Solution

@XmlElement(nillable=true)

You just need to specify `@XmlElement(nillable=true)` on your field/property to get this behaviour:

@XmlElement(nillable=true)
private String foo;

Generating From an XML Schema

Below I'll demonstrate how to generate this mapping if you are staring from an XML schema.

XML Schema (schema.xsd)

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="foo">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="myStringElementName" type="xs:string"
                    nillable="true" minOccurs="0" />
                <xs:element name="myIntElementName" type="xs:int"
                    nillable="true" minOccurs="0" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Why you get a property of type `JAXBElement`

A property of type `JAXBElement` is generated in your model because you have a nillable element this is `minOccurs="0"`. The use of `JAXBElement` allows the model to differentiate between an missing element (property is null) and the presence of the element with `nil="true"` (JAXBElement with nil flag set).

<xs:element name="myStringElementName" type="xs:string"
                        nillable="true" minOccurs="0" />

External Binding File (binding.xml)

An external binding file can be specified to tell the JAXB implementation not to generate any properties of type `JAXBElement`. Note this will make it impossible for JAXB to round trip all XML documents.

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings version="2.0"
               xmlns:jaxb="http://java.sun.com/xml/ns/jaxb">
    <jaxb:bindings>
        <jaxb:globalBindings generateElementProperty="false"/>
    </jaxb:bindings>
</jaxb:bindings>

XJC Call

Below is an example of how to leverage an external binding file from the XJC Call

xjc -b binding.xml schema.xsd

Generated Model (Foo)

The generated model will look something like the following:

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "myStringElementName",
    "myIntElementName"
})
@XmlRootElement(name = "foo")
public class Foo {

    @XmlElement(nillable = true)
    protected String myStringElementName;
    @XmlElement(nillable = true)
    protected Integer myIntElementName;

    public String getMyStringElementName() {
        return myStringElementName;
    }

    public void setMyStringElementName(String value) {
        this.myStringElementName = value;
    }

    public Integer getMyIntElementName() {
        return myIntElementName;
    }

    public void setMyIntElementName(Integer value) {
        this.myIntElementName = value;
    }

}

For More Information

- http://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html

Problem

I am receiving XML from a server whose schema specifies nearly every element as: ``` <xs:element name="myStringElementName" type="xs:string" nillable="true" minOccurs="0"/> <xs:element name="myIntElementName" type="xs:int" nillable="true" minOccurs="0"/> ``` I'm trying to find a clean way to convert every element that I receive that is marked as `xsi:nil="true"` to a null when it is unmarshalled into a JAXB object. So something like this: ``` <myIntElementName xsi:nil="true" /> ``` Should result in my JAXB object having a `myIntElementName` property with a value of null, rather than a `JAXBElement` object with a nil property set to true (or anything along those lines). I don't have any control over the system that is sending me the XML that uses the `nillable` attribute, so I need to convert this on my end when I receive it.

Original source