JAXB: Problem deserializing a class B that extends a class A

Please consider the following example:

There is a ClassA and a ClassB which extends it. My problem is now that I have to unmarshall a ClassB from an xml file. Please note that ClassA can not be changed as it is not under my control.

Several problems are noted in this example:

The main problem is that ClassA does not have a default no-arg constructor which is required by JAXB without Adapter. Therefore I implemented MyAdapter which maps ClassB to the simple class ValB which can be processed by JAXB without any problems.

The main problem is how to make JAXB use this adapter? Neither defining the @XmlJavaTypeAdapter on class level nor registering the Adapter to the unmarshaller does it.

Does anybody know how to make JAXB use MyAdapter so that the unmarshaller returns an object that is an instance of ClassA?

public class JaxbTest {

    public static abstract class ClassA {
        public ClassA(String id) {
        }
    }

    @XmlRootElement
    @XmlJavaTypeAdapter(MyAdapter.class) // does not have an effect
    public static class ClassB extends ClassA {

        public String text;

        public ClassB() {
            super("");
        }
    }

    public static class ValB {
        public String text;
    }

    public static class MyAdapter extends XmlAdapter<ValB, ClassB> {

        @Override
        public ClassB unmarshal(ValB v) throws Exception {
            ClassB b = new ClassB();
            b.text = v.text;
            return b;
        }

        @Override
        public ValB marshal(ClassB v) throws Exception {
            ValB b = new ValB();
            b.text = v.text;
            return b;
        }

    }

    public static void main(String[] args) {
        try {
            JAXBContext context = JAXBContext.newInstance(ClassB.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            unmarshaller.setAdapter(new MyAdapter()); // does not have an effect
            ClassA a = (ClassA) unmarshaller.unmarshal(new File("test.xml"));
            // do somthing with a
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

BTW: Don't take the code too serious - it is just an example demonstrating the problem. I know that the definition of ClassA and ClassB are not really useful.

6
задан Robert 16 December 2010 в 10:30
поделиться