@XmlSee也是另类

时间:2011-11-29 21:51:15

标签: java inheritance jaxb

我有以下内容:

class A{
    @XmlElement
    String name;

    //getters and setters
}

class B extends A{
    @XmlElement
    String height;

    //getters and setters
}

最后我有

@XmlRootElement
class P{
    @XmlElement
    List<A> things;

    //getters and setters
}

如果我这样做

List<A> l = new ArrayList<A>();
l.add(new B('hello', 20)) //Add new B with height of 20 and name hello

P p = new P();
p.setThings(l); //Set things to list of B's.

并且编组P,我只将场地作为事物的一部分而非高度。

我知道我可以在A中添加@XmlSeeAlso(B.class)并且它都可以工作。

但问题是我不知道B以外的所有扩展类,因为A可能会在运行时扩展。

如何在运行时动态定义@XmlSeeAlso?

2 个答案:

答案 0 :(得分:2)

这取决于您创建JAXBContext的方式。可以使用所有类的显式列表调用newInstance method,该方法的文档也提供了类似的示例。

  

客户端应用程序必须提供新上下文对象需要识别的类列表。不仅新的上下文将识别指定的所有类,而且它还将识别从指定的类静态直接/间接引用的任何类。引用类的子类和@XmlTransient引用的类未在JAXBContext中注册。例如,在下面的Java代码中,如果你执行newInstance(Foo.class),新创建的JAXBContext将识别Foo和Bar,但不识别Zot或FooBar:

class Foo {
    @XmlTransient FooBar c;
    Bar b;
}
class Bar { int x; }
class Zot extends Bar { int y; }
class FooBar { }

修改:如果您至少知道潜在jaxb类的包名称,也可以create a context given a context path

如果无法实现上述目的,您还可以根据要序列化的对象在运行时创建类列表。我认为最好尝试重构代码以使其不必要。以下代码未经测试:

Set<Class> classes = new HashSet<Class>();
classes.add(p.getClass());
for (A a : p.getThings()) {
    classes.add(a.getClass());
}
JAXBContext context = JAXBContext.newInstance(classes.toArray(new Class[classes.size()]));

答案 1 :(得分:1)

请注意,@XmlSeeAlso也可以在网络服务上添加注释,请参阅此帖:http://weblogs.java.net/blog/kohlert/archive/2006/10/jaxws_and_type.html

如果您的基类无法访问子类(例如,因为它们位于不同的模块中),但您的Web服务具有访问权限,则此功能非常有用。