Pergunta

Estamos usando Jersey (biblioteca Java Rest) para um projeto nos últimos meses e adorando. Mas esta semana se deparou com um problema com o JAXB.

O que eu tenho é um elemento que tem 2 filhos, cada um deles tem filhos onde alguns de seus filhos se referenciam.

Deixe -me mostrar algum código.

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

Então, temos 1 raiz, 2 pais e 3 filhos.

Se eu enviar isso para cima e para baixo no caminho Jaxb, pareço recuperar 4 filhos.
Cada pai tem sua própria cópia do Child2.

Existe alguma maneira de fazer com que o JAXB serializasse o relacionamento e mostre que os pais1 e os pais2 apontam para o mesmo objeto?

Só encontramos esse problema recentemente, quando elementos mais complexos estavam sendo transmitidos.

Se não há como fazer com que o JAXB faça isso (é o que eu acredito no momento), alguém tem alguma sugestão de uma maneira de fazer alguma magia em Jersey para reinstalar o relacionamento?

Foi útil?

Solução

Isso não é um problema com o JAXB, mas é um problema com o seu modelo. Como você gostaria que o JAXB renderizasse seus relacionamentos no XML, quando o XML não fornece um mecanismo padrão para expressar isso? Tanto o consumidor quanto o produtor do XML precisariam ter uma camada de lógica de negócios que concordaria com a representação.

Eu sugiro que você precise remodelar seus dados. Por exemplo, em vez de ter os filhos como estando contidos dentro dos pais, você pode achatar as coisas:

<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"/>

Qualquer que seja o mecanismo lê e escrever essa estrutura terá que saber o que tudo isso significa, mas não vejo outra maneira legal de fazer isso.

Outro ponto de interesse é que Xstream tem Suporte para referências de objetos Quando serializa/desserializa os gráficos de objetos, mas é um mecanismo totalmente proprietário.

Outras dicas

O JAXB suporta referências de não contenção entre objetos na árvore usando uma combinação de @xmlid/ @xmlidref. Um requisito para isso é que todos os objetos na árvore também devem ser referenciados por um relacionamento de contenção. No seu modelo, isso pode envolver dar raiz uma coleção de crianças.

Abaixo seria uma versão modificada do seu código:

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

Então suas aulas de modelo seriam:

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;

}

O XML resultante seria:

<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>

Você poderia fazer isso escrevendo uma classe adaptadora para a classe raiz, que no UnarShalling pode limpar os objetos filhos para remover as duplicatas.

Apenas um pensamento rápido: faça o Child Objetos implementam um adequado equals() método?

Como já foi declarado em outras respostas. Este é o design do JAXB.

O que você poderia fazer é colar manualmente as várias cópias do que você acredita ser o mesmo objeto antes da serialização. Então você não precisaria do seu próprio ID distinto para objetos, para que você pudesse distribuir clones separados de apenas outros objetos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top