2011-11-29 11 views
6

tengo el siguiente:@XmlSeeAlso alternativa

class A{ 
    @XmlElement 
    String name; 

    //getters and setters 
} 

y

class B extends A{ 
    @XmlElement 
    String height; 

    //getters and setters 
} 

fin he

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

    //getters and setters 
} 

Si hago

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. 

y mariscal P, solo obtengo el campo como parte de las cosas y no como altura.

Sé que puedo agregar @XmlSeeAlso (B.class) en A y todo funcionará.

Pero el problema es que no conozco todas las clases ampliadas además de B, ya que A puede extenderse en tiempo de ejecución.

¿Cómo defino dinámicamente @XmlSeeAlso en tiempo de ejecución?

Respuesta

2

Esto depende de cómo esté creando su JAXBContext. Se puede llamar al newInstance method con una lista explícita de todas sus clases, la documentación para ese método también proporciona un ejemplo similar.

La aplicación del cliente debe proporcionar una lista de clases que el nuevo objeto de contexto debe reconocer. No solo el nuevo contexto reconocerá todas las clases especificadas, sino que también reconocerá las clases a las que se hace referencia directa o indirectamente de forma estática de las clases especificadas. Las subclases de las clases referenciadas y las clases referenciadas @XmlTransient no están registradas con JAXBContext. Por ejemplo, en el siguiente código Java, si lo hace newInstance (Foo.class), la recién creada JAXBContext reconocerá tanto foo y bar, pero no Zot o FooBar:

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

Editar: Si usted conoce al menos los nombres de los paquetes de clases jaxb potenciales también podría create a context given a context path.

Si lo anterior no es posible, también podría crear la lista de clases en tiempo de ejecución, según el objeto que desea serializar. Creo que sería mejor intentar refactorizar tu código para que esto no sea necesario. El código siguiente se ha probado:

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

Gracias por la respuesta. newInstance se llama en el mismo proyecto donde se definen A y P (es un proyecto de maven común). El proyecto de la Clase B depende de ese proyecto, por lo que newInstance no tiene conocimiento de la clase B. Supongo que esto es imposible de hacer en JAXB? –

+0

@Ken Hirakawa: De hecho, es una situación difícil, he ampliado mi respuesta con una posible solución. –