I am new in JAXB and I would like to do something i don't know if it's doable. I have a java class to marshall like this :
@XmlAccessorType(XMLAccessType.NONE)
public class MyClass {
@XmlElement
private String a = "x";
@XmlElement
private String b = "xx";
@XmlElement
private boolean c = true;
...
}
and want XML output like this :
<?xml ...?>
<MyClass>
<a>x</a>
<b>xx</b>
<c value="true"/>
</MyClass>
One solution i have in mind is to use a boolean wrapper class to make it work, but i would like to avoid this as it takes me away the ability to use boolean primitive true, false.
Can we do that in JAXB?
Leverage An XmlAdapter
You could create an XmlAdapter
to get the behaviour you are looking for. An XmlAdapter
converts a domain object into another type for the purposes of marshalling and unmarshalling.
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class BooleanAdapter extends XmlAdapter<BooleanAdapter.AdaptedBoolean, Boolean> {
public static class AdaptedBoolean {
@XmlAttribute
public boolean value;
}
@Override
public Boolean unmarshal(AdaptedBoolean adaptedBoolean) throws Exception {
return adaptedBoolean.value;
}
@Override
public AdaptedBoolean marshal(Boolean v) throws Exception {
AdaptedBoolean adaptedBoolean = new AdaptedBoolean();
adaptedBoolean.value = v;
return adaptedBoolean;
}
}
To Use the XmlAdapter
To use the XmlAdapter
your mapped field will need to be of type Boolean
instead of boolean
. You accessor methods can still be boolean
if you want.
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlAccessorType(XmlAccessType.NONE)
public class MyClass {
@XmlElement
private String a = "x";
@XmlElement
private String b = "xx";
@XmlElement
@XmlJavaTypeAdapter(BooleanAdapter.class)
private Boolean c = true;
public boolean getC() {
return c;
}
public void setC(boolean c) {
this.c = c;
}
}
The XML output of your class is:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<myClass>
<a>x</a>
<b>xx</b>
<c>true</c>
</myClass>
If you want the boolean
value to result in
<c value="true" />
then you need a wrapper element around the boolean c
field. This can be of type Boolean
or some other custom type with the boolean c
inside of it, and marked with @XmlAttribute
.
Example:
class MyBool {
@XmlAttribute(name="value")
private boolean c = true;
}
@XmlAccessorType(XmlAccessType.NONE)
class MyClass {
@XmlElement
private String a = "x";
@XmlElement
private String b = "xx";
@XmlElement
private MyBool c = new MyBool();
}
Output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<myClass>
<a>x</a>
<b>xx</b>
<c value="true"/>
</myClass>
Note:
If you don't want to use a wrapper, you can still annotate boolean c
with @XmlAttribute
like this:
@XmlAttribute(name="value")
private boolean c = true;
But then it will be rendered as an attribute of the wrapper class which in this case is MyClass
, so the output will be:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<myClass value="true">
<a>x</a>
<b>xx</b>
</myClass>