Search code examples
annotationsjaxbhashmapjaxb2unmarshalling

JAXB reuse annotation from parent class and access preset field


There is a class called Parent which in generated from a xsd file and holds a fully JABX annotated List. This class can't be changed. Furthermore there is a Child extends Parent class that would like to use an XmlAdapter to convert the List to a HashMap. The HashMap field will have (could have) the same name and map to the same xsd element.

Can JAXB set a field with the same name multiple times? Does JAXB try to use the already filled List of the parent class as input for the XmlAdapter in the child class? I presume this won't work the way I am hoping for.

How can this task be done neatly?

EDIT: My real question is really how to use JAXB autogenerated beans that shouldn't be edited and still be able to use a hashmap.

Here's my code which doesn't work. The map stays null. Sry for the bad code formatting.

public class Adapter extends XmlAdapter<LinkedList<A>,HashMap<String,A>> {

    @Override
    public LinkedList<A> marshal(HashMap<String, A> v) throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public HashMap<String, A> unmarshal(LinkedList<A> v) throws Exception {
        HashMap<String, A> map = new HashMap<String, A>();
        for(A a:v) {
            map.put(a.k, a);
        }
        return map;
    }
}

@XmlRootElement
public class Child extends Parent {

    @XmlElement(name="a")
    @XmlJavaTypeAdapter(Adapter.class)
    HashMap<String,A> map;
}

@XmlRootElement
public class Parent {

    @XmlElement(name="a")
    LinkedList<A> values = new LinkedList<A>();
}

public class XmlTest {

    public static void main(String[] args) throws ParserConfigurationException, JAXBException, SAXException, IOException {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(new File("test.xml"));
        JAXBContext jc = JAXBContext.newInstance(Child.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Child instance = unmarshaller.unmarshal(doc,Child.class).getValue();
    }
}

Here is class A:

public class A {

    @XmlAttribute
    String v;

    @XmlAttribute
    String k;
}

Here the test.xml:

<root>
  <a v="1" k="a"/>
  <a v="2" k="b"/>
</root>

Solution

  • Have a look at example by Blaise Doughan. In your case class A is class MyMapEntryType, class Parent is class MyMapType. class Child should not extend Parent, as it is intermediate class just for JAXB to be able to map the list of <a> elements.