3

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?

uxout
  • 33
  • 4
  • 1
    After searching around ("jaxb flattened element" and related) I suspect this can be done with `@XmlJavaTypeAdapter` (http://stackoverflow.com/questions/18272059/jaxb-xmladapter-for-arbitrary-xml), but I don't know enough about JAXB to be certain, so I'm giving this suggestion as a comment rather than answer. – Brett Kail Dec 18 '14 at 16:28
  • 1
    @bkail - Here is how the `XmlAdapter` approach would look: http://stackoverflow.com/a/27551339/383861 – bdoughan Dec 18 '14 at 16:35

2 Answers2

3

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;
    }
}
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Thanks for the answer, i did try to use XMLAdapter but didn't know i could use it this way. I'm gonna try your solution :) – uxout Dec 19 '14 at 16:46
  • 1
    Hello, happy new year ! I tested your solution and it works fine. Thank you very much, have a good day ! ^^ – uxout Jan 05 '15 at 08:40
1

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>
icza
  • 389,944
  • 63
  • 907
  • 827
  • I dont want to change my boolean class because it is used in a lot of others classes and i loose the ability to use boolean like 'boolean a = true'. I'll try your solution if i can't find another one. Thanks for your reply :) – uxout Dec 19 '14 at 16:51