【问题标题】:JAXB doesn't unmarshal list of interfacesJAXB 不会解组接口列表
【发布时间】:2012-06-20 20:40:25
【问题描述】:

似乎 JAXB 无法读取它所写的内容。考虑以下代码:

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 加载。不幸的是,这段代码不能正常工作:集合已保存,但无法加载!预期的输出是

1
2
3
some xml
1
2
3

但不幸的是,实际输出是

1
2
3
some xml
com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to testapplication1.IFoo

显然,我需要以不同的方式使用注释?还是放弃 JAXB 并寻找其他东西?我可以为所有我不想(de)编组的类编写“XMLNode toXML()”方法,但是......

【问题讨论】:

  • 查看文档以了解@XmlSeeAlso 的用法
  • stackoverflow.com/questions/4144296/… 的可能重复项,它还询问接口类型的列表,并且在接受的答案中有不同的工作方法。

标签: java xml jaxb


【解决方案1】:

试试下面的@XmlAnyElement(lax=true)lax 标志告诉 JAXB (JSR-222) 实现根据其 @XmlRootElement@XmlElementDecl 注释将元素与域对象匹配。没有它,内容将被视为 DOM 节点。

@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);
    }
}

更多信息

【讨论】:

  • 它有效。谢谢!但是天哪,所有这些 JAXB 东西就像黑魔法一样,我还没有找到一个通俗易懂的指南。
  • @Joker_vD - 查看我的 Java XML 和 JSON 绑定博客 (blog.bdoughan.com) 和 EclipseLink JAXB (MOXy) 用户指南 (wiki.eclipse.org/EclipseLink/UserGuide/MOXy)
  • 与您在对下面链接的先前问题的回答中提供的方法相比,这种方法有哪些优点和缺点? (例如,较早的答案似乎假定持有该列表的类知道这组实现。)stackoverflow.com/a/4145801/202009
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 2014-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多