macktheknife
macktheknife

Reputation: 41

Is it possible to provide JAXB with a mapping information regarding element values?

I'm using JAXB to generate a xml file from my java objects (xml export), as well as the other way arround (xml import).

In some cases I'm using a "magic-number" to initialize a integer class attribute, because 0 is also valid an I want to initialize the attribute and mark it as "not-yet-edited".

In the xml output generated from JAXB I would be happy if this magic-number is not existing. Is it possible to provide JAXB with something like a mapping information?

Please have a look at the example.

Example:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="my-root") 
public class ExampleClass {

    /** integer value which represents empty */
    public static final int EMPTY_INT = Integer.MAX_VALUE;

    /** my id */
    @XmlElement(name="id")
    private int mMyId = EMPTY_INT;
    public void setMyId(int myId) {
        mMyId = myId;
    }
    public int getMyId() {
        return mMyId;
    }
}

JAXB generates someting like:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<my-root>
    <id>2147483647</id>
</my-root>

What I want is:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<my-root>
    <id></id>
</my-root>

I need to tell JAXB to generate "nothing" (see example) if the attribute value is EMPTY_INT and the other way arround (import).

Is that possible somehow? Or are there other ways to reach that goal?

Thank you for your help. Steffen

UPDATE:


Based on the answers I tried the following:

Note: The code is shorted (e. g. without imports)

1) add a class: Mydapter

public class MyAdapter extends XmlAdapter<String, Integer> {
    @Override
    public Integer unmarshal(String val) throws Exception {
        System.out.println("Debug1");
        return Integer.parseInt(val);
    }
    @Override
    public String marshal(Integer val) throws Exception {
        System.out.println("Debug2");
        if (val == Integer.MAX_VALUE) {
            return "";
        } else {
            return val.toString();
       }
    }        
}

2) adapted ExampleClass to use "Integer" instead of "int" and annotade it

@XmlJavaTypeAdapter(MyAdapter.class)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="my-root") 

public class ExampleClass {

    /** integer value which represents empty */
    public static final int EMPTY_INT = Integer.MAX_VALUE;

    /** my id */
    @XmlElement(name="id")
    private Integer mMyId = EMPTY_INT;
    public void setMyId(int myId) {
        mMyId = myId;
    }
    public int getMyId() {
        return mMyId;
    }
}

3) Code performing the xml export

public class XMLImportExport {

    public static void exportToXml(File xmlFile) throws Exception {

        JAXBContext jc = JAXBContext.newInstance(ExampleClass.class);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(new ExampleClass(), xmlFile);
    }
}

4) xml output is still

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<my-root>
    <id>2147483647</id>
</my-root>

Thank you, Steffen

Upvotes: 1

Views: 131

Answers (1)

Dave Richardson
Dave Richardson

Reputation: 5005

Annotate mMyId with @XmlJavaTypeAdapter(YourAdapter.class) and then write an adapter to do the job. Something like this (untested) :

public class YourAdapter extends XmlAdapter<String, Integer> {
    public Integer unmarshal(String val) throws Exception {
        return Integer.parseInt(val);
    }
    public String marshal(Integer val) throws Exception {
        if ( val == Integer.MAX_VALUE) {
            return "";
        } else {
            return val.toString();
        }
    }        
}

Upvotes: 1

Related Questions