I will try to provide a SSCCE of my problem.
I have this hierarchy of classes:
Class Base:
@XmlRootElement
@XmlSeeAlso({ A.class, B.class })
@XmlAccessorType(XmlAccessType.FIELD)
public class Base {
@XmlAttribute
private String baseData;
public String getBaseData() {
return baseData;
}
public void setBaseData(String baseData) {
this.baseData = baseData;
}
}
Class A extends Base
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="A", propOrder = { "dataA1", "dataA2" })
@XmlRootElement(name = "Base", namespace = "")
public class A extends Base {
private String dataA1;
private String dataA2;
public String getDataA1() {
return dataA1;
}
public void setDataA1(String dataA1) {
this.dataA1 = dataA1;
}
public String getDataA2() {
return dataA2;
}
public void setDataA2(String dataA2) {
this.dataA2 = dataA2;
}
}
Class B extends Base
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="B", propOrder = { "dataB1", "dataB2" })
@XmlRootElement(name = "Base", namespace = "")
public class B extends Base {
private String dataB1;
private String dataB2;
public String getDataB1() {
return dataB1;
}
public void setDataB1(String dataB1) {
this.dataB1 = dataB1;
}
public String getDataB2() {
return dataB2;
}
public void setDataB2(String dataB2) {
this.dataB2 = dataB2;
}
}
But when I try to test it:
public class Test {
public static void main(String[] args) throws Exception {
Base base = new A();
base.setBaseData("BaseDataA");
((A) base).setDataA1("DataA1");
((A) base).setDataA2("DataA2");
JAXBContext jc = JAXBContext.newInstance(Base.class, A.class, B.class);
// Marshal the object
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter sw = new StringWriter();
marshaller.marshal(base, sw);
// Unmarshal the object
Unmarshaller unmarshaller = jc.createUnmarshaller();
String generatedXml = sw.toString();
System.out.println(generatedXml);
Base objectFromUnmarshall = (Base) unmarshaller.unmarshal(new StringReader(generatedXml));
System.out.println(objectFromUnmarshall);
// Re-marshal the object
System.out.println("");
sw = new StringWriter();
marshaller.marshal(objectFromUnmarshall, sw);
System.out.println(sw.toString());
}
}
This is the output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Base baseData="BaseDataA">
<dataA1>DataA1</dataA1>
<dataA2>DataA2</dataA2>
</Base>
jaxb.B@5c0369c4
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Base baseData="BaseDataA"/>
I marchal an object A, but when unmarshalling it creates an instance of B!
Why? How can I tell him to unmarshalh to the good instance?
NOTE: I am using Sun JAXB implementation and I cannot change it.
Well, the only way I have found to handle it is to use an XMLAdapter (based in this great article ).
public class BaseAdapter extends XmlAdapter<BaseAdapter.BaseHandler,Base>{
@Override
public Base unmarshal(BaseHandler baseHandler) throws Exception {
if (null == baseHandler) {
return null;
}
if (null != baseHandler.dataA1) {
A a = new A();
a.setDataA1(baseHandler.dataA1);
a.setDataA2(baseHandler.dataA2);
return a;
} else {
B b = new B();
b.setDataB1(baseHandler.dataB1);
b.setDataB2(baseHandler.dataB2);
return b;
}
}
@Override
public BaseHandler marshal(Base base) throws Exception {
if (null == base) {
return null;
}
BaseHandler baseHandler = new BaseHandler();
if (base instanceof A) {
A a = (A) base;
baseHandler.dataA1 = a.getDataA1();
baseHandler.dataA2 = a.getDataA2();
} else {
B b = (B) base;
baseHandler.dataB1 = b.getDataB1();
baseHandler.dataB2 = b.getDataB2();
}
return baseHandler;
}
public static class BaseHandler {
public String dataA1;
public String dataA2;
public String dataB1;
public String dataB2;
}
}
Here you are the complete SSCCE code if somebody is interested.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.