Convert nil="true" to null during unmarshal operation
Asked Answered
G

1

3

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.

Golgotha answered 20/9, 2012 at 19:31 Comment(0)
S
6

@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

Saddlery answered 20/9, 2012 at 19:43 Comment(2)
Has anyone told you lately that you're awesome? One other question if you don't mind. Should I always annotate the property in my JAXB class instead of the associated getter/setter method?Golgotha
Annotating the getter (or setter) is usually the safest thing to do. For example if you use the same model for both JAXB and JPA, then the JPA implementation my modify the byte codes to support lazy loading triggered on calling the getter. For more information see: blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.htmlSaddlery

© 2022 - 2024 — McMap. All rights reserved.