@XmlSee也是另类

Ken*_*awa 6 java inheritance jaxb

我有以下内容:

class A{
    @XmlElement
    String name;

    //getters and setters
}
Run Code Online (Sandbox Code Playgroud)

class B extends A{
    @XmlElement
    String height;

    //getters and setters
}
Run Code Online (Sandbox Code Playgroud)

我终于有了

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

    //getters and setters
}
Run Code Online (Sandbox Code Playgroud)

如果我做

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.
Run Code Online (Sandbox Code Playgroud)

和元帅P,我只把场地作为事物的一部分,而不是高度.

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

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

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

Jör*_*ann 2

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

客户端应用程序必须提供新上下文对象需要识别的类列表。新上下文不仅会识别所有指定的类,而且还会识别从指定类直接/间接静态引用的任何类。引用类的子类和 @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 { }
Run Code Online (Sandbox Code Playgroud)

编辑:如果您至少知道潜在 jaxb 类的包名称,您还可以根据给定的 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()]));
Run Code Online (Sandbox Code Playgroud)