Note. I am EclipseLink JAXB (MOXy) and a member of the JAXB 2 group (JSR-222) .
I entered an extension request to add this behavior to EclipseLink JAXB (MOXy):
WORK AROUND
How it works, if all the displayed fields / String properties are mapped to XML elements, the following XmlAdapter approach may work for you:
Nullstringadapter
This XmlAdapter will march String instances as an object named AdaptedString . AdaptedString contains a String value, as well as a field mapped to the xsi:nil attribute. In the XmlAdapter we set the value of this field depending on whether the String value is zero.
package forum8841221; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.*; public class NullStringAdapter extends XmlAdapter<NullStringAdapter.AdaptedString, String> { @Override public AdaptedString marshal(String v) throws Exception { AdaptedString adaptedString = new AdaptedString(); if(null == v) { adaptedString.nil = true; } adaptedString.value = v; return adaptedString; } @Override public String unmarshal(AdaptedString v) throws Exception { return v.value; } public static class AdaptedString { @XmlAttribute(namespace="http://www.w3.org/2001/XMLSchema-instance") public Boolean nil; @XmlValue @XmlJavaTypeAdapter(VoidStringAdapter.class) public String value; } public static class VoidStringAdapter extends XmlAdapter<String, String> { @Override public String marshal(String v) throws Exception { return v; } @Override public String unmarshal(String v) throws Exception { return v; } } }
package info
We can register that we want this XmlAdapter applied to all displayed fields / String properties on this package by registering the XmlAdapter at the package level.
@XmlJavaTypeAdapter(value=NullStringAdapter.class, type=String.class) @XmlSchema(xmlns={@XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")}) package forum8841221; import javax.xml.bind.annotation.adapters.*; import javax.xml.bind.annotation.*;
Root
The following is the domain class that I used for this example. It has several String properties, one of which is annotated using @XmlElement (nillable = true)
package forum8841221; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Root { private String a; private String b; private String c; private String d; public String getA() { return a; } public void setA(String a) { this.a = a; } public String getB() { return b; } public void setB(String b) { this.b = b; } public String getC() { return c; } public void setC(String c) { this.c = c; } @XmlElement(nillable=true) public String getD() { return d; } public void setD(String d) { this.d = d; } }
Demo
package forum8841221; 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(Root.class); Root root = new Root(); root.setB("B"); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } }
Exit
<?xml version="1.0" encoding="UTF-8"?> <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <a xsi:nil="true"/> <b>B</b> <c xsi:nil="true"/> <d xsi:nil="true"/> </root>