Question

I am using JAXB2 to serialize object to xml.

Is there any way how to force it to create entire object structure like in following example even if it is not filled in backing object?

This is my intended result even without having asignee property set.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<note>
    <to xsi:nil="true"/>
    <from xsi:nil="true"/>
    <header xsi:nil="true"/>
    <body>text</body>
    <assignee>
        <name xsi:nil="true"/>
        <surname xsi:nil="true"/>
    </assignee>
</note>

I use following code for serialization:

JAXBContext jc = JAXBContext.newInstance(dataObject.getClass());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, schemaLocation);
marshaller.setProperty(Marshaller.JAXB_ENCODING, charset);
marshaller.marshal(dataObject, outputStream);
Was it helpful?

Solution

You can do the following:

Note

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement
@XmlType(propOrder={"to", "from", "header", "body", "assignee"})
public class Note {

    private String to;
    private String from;
    private String header;
    private String body;
    private Assignee assignee;

    @XmlElement(nillable=true)
    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    @XmlElement(nillable=true)
    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    @XmlElement(nillable=true)
    public String getHeader() {
        return header;
    }

    public void setHeader(String header) {
        this.header = header;
    }

    @XmlElement(nillable=true)
    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public Assignee getAssignee() {
        return assignee;
    }

    public void setAssignee(Assignee assignee) {
        this.assignee = assignee;
    }

}

Assignee

We will need to have a means to no when an unmarshalled instance of Assignee should be interpreted as null. I have added an isNull() method that returns true if all the fields are null.

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(AssigneeAdapter.class)
public class Assignee {

    private String name;
    private String surname;

    @XmlElement(nillable=true)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlElement(nillable=true)
    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public boolean isNull() {
        return null == name && null == surname;

    }
}

AssigneeAdapter

The AssigneeAdapter uses both the Assignee object for the value type and bound type. This class leverages the isNull() method we added on Assignee:

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class AssigneeAdapter extends XmlAdapter<Assignee, Assignee> {

    @Override
    public Assignee unmarshal(Assignee v) throws Exception {
        if(v.isNull()) {
            return null;
        }
        return v;
    }

    @Override
    public Assignee marshal(Assignee v) throws Exception {
        if(null == v) {
            return new Assignee();
        }
        return v;
    }

}

Demo

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(Note.class);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(new Note(), System.out);
    }
}

For more information on XmlAdapter see:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top