Question

Nous sommes à l'aide de Jersey (Java RESTE de la bibliothèque) pour un projet depuis quelques mois et à l'aimer.Mais cette semaine ont eu un problème avec JAXB.

Ce que j'ai est un élément qui a 2 enfants, chacun d'eux ont les enfants, où certains de leurs enfants font référence les uns aux autres.

Laissez-moi vous montrer un peu de code.

Root root = new Root();

Parent parent1 = new Parent();
Parent parent2 = new Parent();

root.add(parent1);
root.add(parent2);

Child child1 = new Child();
Child child2 = new Child();
Child child3 = new Child();

parent1.add(child1);
parent1.add(child2);

parent2.add(child2);
parent2.add(child3);

Nous avons donc racine 1, 2 parents et 3 enfants.

Si j'envoie ce haut et en bas de la JAXB chemin, j'ai l'impression de revenir de 4 enfants.
Chaque Parent a sa propre copie de l'enfant2.

Est-il de toute façon à obtenir JAXB pour serialise la relation et de montrer que les deux parent1 et parent2 pointent vers le même objet?

Nous n'avons trouvé que cette question récemment, lorsque des éléments plus complexes ont été transmises.

Si il n'y a aucun moyen d'obtenir JAXB pour ce faire (c'est ce que je crois pour le moment), quelqu'un aurait-il des suggestions d'une manière que je pourrais faire de la magie en Jersey de rétablir la relation?

Était-ce utile?

La solution

Ce n'est pas un problème avec JAXB tellement que c'est un problème avec votre modèle.Comment voudriez-vous JAXB pour rendre vos relations dans XML, lorsque XML fournit pas de mécanisme standard pour exprimer cela?À la fois consommateur et producteur de l'XML aurait besoin d'avoir une couche de logique métier qui serait d'accord sur le respresentation.

Je suggère que vous avez besoin de remodeler vos données.Par exemple, plutôt que d'avoir des enfants comme étant contenue à l'intérieur de la parents, vous pouvez aplatir les choses:

<parent id="parent1">
   <child ref="child1"/>
   <child ref="child2"/>
</parent>

<parent id="parent2">
   <child ref="child2"/>
   <child ref="child3"/>
</parent>

<child id="child1"/>
<child id="child2"/>
<child id="child3"/>

Quel que soit le mécanisme lit et écrit de cette structure pour savoir ce que tout cela signifie, mais je ne vois pas d'autre façon agréable de ce faire.

Un autre point d'intérêt est que XStream n'ont soutien pour les références de l'objet quand il sérialise/désérialise les graphes d'objets, mais c'est un tout mécanisme propriétaire.

Autres conseils

JAXB prend en charge la compression des références entre objets dans l'arborescence à l'aide d'une combinaison de @XmlID/@XmlIDREF.Une condition pour cela est que tous les objets dans l'arborescence doit également être référencé par un confinement de la relation.Dans votre modèle, cela peut impliquer en donnant la Racine de la collection de l'Enfant.

Ci-dessous serait une version modifiée de votre code:

Root root = new Root(); 

Parent parent1 = new Parent(); 
Parent parent2 = new Parent(); 

root.add(parent1); 
root.add(parent2); 

Child child1 = new Child(); 
child1.id = "1";
root.add(child1);
parent1.add(child1); 

Child child2 = new Child();
child2.id = "2";
root.add(child2);
parent1.add(child2); 
parent2.add(child2); 

Child child3 = new Child();
child3.id = "3";
root.add(child3);
parent2.add(child3);

Alors votre modèle de classes ressemblerait à:

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Root {

    public List<Parent> parent = new ArrayList<Parent>();
    public List<Child> child = new ArrayList<Child>();

    public void add(Parent parent1) {
        parent.add(parent1);
    }

    public void add(Child child1) {
        child.add(child1);
    }
}

import javax.xml.bind.annotation.XmlIDREF;

public class Parent {

    @XmlIDREF
    public List<Child> child = new ArrayList<Child>();

    public void add(Child child1) {
        child.add(child1);
    }

}

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlID;

public class Child {

    @XmlID
    @XmlAttribute
    public String id;

}

Le XML résultant ressemblerait à:

<root>
    <parent>
        <child>1</child>
        <child>2</child>
    </parent>
    <parent>
        <child>2</child>
        <child>3</child>
    </parent>
    <child id="1"/>
    <child id="2"/>
    <child id="3"/>
</root>

vous pourriez potentiellement faire par l'écriture d'une classe d'adaptateur pour la classe Racine, qui, sur unmarshalling peut nettoyer l'enfant les objets à supprimer les doublons.

Juste une petite réflexion:faire l' Child les objets de mettre en œuvre une bonne equals() méthode?

Comme déjà dit dans d'autres réponses.C'est la conception de JAXB.

Ce que vous pourriez faire est d'manuellement la colle de plusieurs copies de ce que vous croyez est le même objet avant de sérialisation.Ensuite, vous n'avez pas besoin de votre propre ID de l'objet, de sorte que vous pourriez dire en dehors des clones de tout les autres objets.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top