2011-11-29 10 views
6

Ho la seguente:@XmlSeeAlso alternativa

class A{ 
    @XmlElement 
    String name; 

    //getters and setters 
} 

e

class B extends A{ 
    @XmlElement 
    String height; 

    //getters and setters 
} 

finalmente ho

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

    //getters and setters 
} 

Se faccio

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. 

e maresciallo P, ottengo solo il campo come parte delle cose e non come altezza.

So che posso aggiungere @XmlSeeAlso (B.class) in A e funzionerà tutto.

Ma il problema è che non conosco tutte le classi estese oltre a B, poiché A può essere esteso in runtime.

Come definire dinamicamente @XmlSeeAlso in runtime?

risposta

2

Questo dipende da come si crea il . Il newInstance method può essere chiamato con un elenco esplicito di tutte le classi, la documentazione per tale metodo fornisce anche un esempio simile.

L'applicazione client deve fornire un elenco di classi che il nuovo oggetto di contesto deve riconoscere. Non solo il nuovo contesto riconoscerà tutte le classi specificate, ma riconoscerà anche tutte le classi che sono referenziate direttamente/indirettamente in modo statico dalle classi specificate. Sottoclassi di classi referenziate o classi di riferimento @XmlTransient non sono registrate con JAXBContext. Ad esempio, nel seguente codice Java, se si fa newInstance (Foo.class), il JAXBContext appena creato riconoscerà sia Foo e bar, ma non Zot o FooBar:

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

Edit: Se conosci almeno i nomi dei pacchetti delle potenziali classi jaxb potresti anche create a context given a context path.

Se quanto sopra non è possibile, è anche possibile creare l'elenco di classi in fase di esecuzione, in base all'oggetto che si desidera serializzare. Penso che sarebbe meglio cercare di rifattorizzare il codice per renderlo inutile. Il codice qui sotto non è testato:

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

Grazie per la risposta. newInstance è chiamato nello stesso progetto di dove sono definiti A e P (è un progetto comune di maven). Il progetto di Classe B dipende da quel progetto, e quindi newInstance non ha conoscenza della classe B. Immagino che sia impossibile farlo in JAXB? –

+0

@Ken Hirakawa: questa è davvero una situazione complicata, ho ampliato la mia risposta con una possibile soluzione. –