2011-11-29 53 views
6

我有以下幾點:@XmlSeeAlso替代

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

這取決於您如何創建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

感謝您的回覆。在與定義A和P的同一項目中調用newInstance(它是一個常見的Maven項目)。 B類的項目取決於該項目,所以newInstance對B類沒有任何知識。我想這在JAXB中是不可能的。 –

+0

@Ken Hirakawa:這確實是一個棘手的情況,我已經用可能的解決方案擴展了我的答案。 –