JAXB不解组接口列表 [英] JAXB doesn't unmarshal list of interfaces
问题描述
似乎JAXB无法读取它写的内容。请考虑以下代码:
It seems JAXB can't read what it writes. Consider the following code:
interface IFoo {
void jump();
}
@XmlRootElement
class Bar implements IFoo {
@XmlElement
public String y;
public Bar() {
y = "";
}
public Bar(String y) {
this.y = y;
}
@Override
public void jump() {
System.out.println(y);
}
}
@XmlRootElement
class Baz implements IFoo {
@XmlElement
public int x;
public Baz() {
x = 0;
}
public Baz(int x) {
this.x = x;
}
@Override
public void jump() {
System.out.println(x);
}
}
@XmlRootElement
public class Holder {
private List<IFoo> things;
public Holder() {
things = new ArrayList<>();
}
@XmlElementWrapper
@XmlAnyElement
public List<IFoo> getThings() {
return things;
}
public void addThing(IFoo thing) {
things.add(thing);
}
}
// ...
try {
JAXBContext context = JAXBContext.newInstance(Holder.class, Bar.class, Baz.class);
Holder holder = new Holder();
holder.addThing(new Bar("1"));
holder.addThing(new Baz(2));
holder.addThing(new Baz(3));
for (IFoo thing : holder.getThings()) {
thing.jump();
}
StringWriter s = new StringWriter();
context.createMarshaller().marshal(holder, s);
String data = s.toString();
System.out.println(data);
StringReader t = new StringReader(data);
Holder holder2 = (Holder)context.createUnmarshaller().unmarshal(t);
for (IFoo thing : holder2.getThings()) {
thing.jump();
}
}
catch (Exception e) {
System.err.println(e.getMessage());
}
当然,这是一个简化的例子。关键是我必须在一个集合中存储两个非常不同的实现类Bar和Baz。好吧,我观察到他们有非常相似的公共接口,所以我创建了一个接口IFoo并使它们实现它。现在,我想要有工具来保存和加载这个集合到XML或从XML加载。不幸的是,这段代码不太有用:集合已保存,但无法加载!预期的输出是
It's a simplified example, of course. The point is that I have to store two very differently implemented classes, Bar and Baz, in one collection. Well, I observed that they have pretty similar public interface, so I created an interface IFoo and made them two to implement it. Now, I want to have tools to save and load this collection to/from XML. Unfortunately, this code doesn't quite work: the collection is saved, but then it cannot be loaded! The intended output is
1
2
3
some xml
1
2
3
但不幸的是,实际产量是
But unfortunately, the actual output is
1
2
3
some xml
com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to testapplication1.IFoo
显然,我需要使用注释以不同的方式?或者放弃JAXB并寻找其他东西?我可以为我不想(de)编组的所有类编写XMLNode toXML()方法,但是......
Apparently, I need to use the annotations in a different way? Or to give up on JAXB and look for something else? I, well, can write "XMLNode toXML()" method for all classes I wan't to (de)marshal, but...
推荐答案
尝试以下 @XmlAnyElement(lax = true)
。 lax
标志告诉JAXB(JSR-222)实现根据 @XmlRootElement
和<来匹配域对象的元素code> @XmlElementDecl 注释。没有它,内容将被视为DOM节点。
Try the following @XmlAnyElement(lax=true)
. The lax
flag tells the JAXB (JSR-222) implementation to match elements to domain objects based their @XmlRootElement
and @XmlElementDecl
annotations. Without it the contents are treated as DOM nodes.
@XmlRootElement
public class Holder {
private List<IFoo> things;
public Holder() {
things = new ArrayList<>();
}
@XmlElementWrapper
@XmlAnyElement(lax=true)
public List<IFoo> getThings() {
return things;
}
public void addThing(IFoo thing) {
things.add(thing);
}
}
更多信息
- http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html
这篇关于JAXB不解组接口列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!