6 votes

@XmlSeeAlso alternative

Je dispose des éléments suivants :

class A{
    @XmlElement
    String name;

    //getters and setters
}

et

class B extends A{
    @XmlElement
    String height;

    //getters and setters
}

Enfin, j'ai

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

    //getters and setters
}

Si je le fais

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.

et marshal P, je n'obtiens le champ qu'en tant que partie des choses et non en hauteur.

Je sais que je peux ajouter @XmlSeeAlso(B.class) dans A et que tout fonctionnera.

Mais le problème est que je ne connais pas toutes les classes étendues autres que B, car A peut être étendu au moment de l'exécution.

Comment définir dynamiquement @XmlSeeAlso à l'exécution ?

2voto

Jörn Horstmann Points 18118

Cela dépend de la façon dont vous créez votre JAXBContext . Les méthode newInstance peut être appelée avec une liste explicite de toutes vos classes, la documentation de cette méthode donne également un exemple similaire.

L'application cliente doit fournir une liste de classes que le nouvel objet contextuel doit reconnaître. Non seulement le nouveau contexte reconnaîtra toutes les classes spécifiées, mais il reconnaîtra également toutes les classes qui sont directement/indirectement référencées statiquement à partir des classes spécifiées. Les sous-classes des classes référencées et les classes référencées @XmlTransient ne sont pas enregistrées dans JAXBContext. Par exemple, dans le code Java suivant, si vous faites newInstance(Foo.class), le JAXBContext nouvellement créé reconnaîtra à la fois Foo et Bar, mais pas Zot ou FooBar :

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

Editer : Si vous connaissez au moins les noms des paquets des classes jaxb potentielles, vous pouvez aussi créer un contexte à partir d'un chemin d'accès au contexte .

Si cela n'est pas possible, vous pouvez également créer la liste des classes au moment de l'exécution, en fonction de l'objet que vous souhaitez sérialiser. Je pense qu'il serait préférable d'essayer de remanier votre code pour rendre cette opération inutile. Le code ci-dessous n'a pas été testé :

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()]));

1voto

robinst Points 9249

Il convient de noter que @XmlSeeAlso peut également être annoté sur un service web, voir cet article : http://weblogs.java.net/blog/kohlert/archive/2006/10/jaxws_and_type.html

Ceci est utile si votre classe de base n'a pas accès aux sous-classes (par exemple parce qu'elles se trouvent dans un module différent), mais que votre service web y a accès.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X