2012-11-21 23 views
6

In contesto RestFul-Webservice (Jersey) Devo eseguire il marshalling/serializzazione di un oggetto grafico in XML e JSON. Per semplicità provo a spiegare il problema con 2-3 classi:XML serializzato JAXB con riferimenti ID anziché contenimento

Person.java

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Person { 

    private String name; 

    // @XmlIDREF 
    @XmlElement(name = "house") 
    @XmlElementWrapper(name = "houses") 
    private Collection<House> houses; 

    public Person() {} 

    public Person(String name, Collection<House> houses) { 
     this.name = name; 
     this.houses = houses; 
    } 
} 

House.java

@XmlAccessorType(XmlAccessType.FIELD) 
public class House { 

    // @XmlID 
    public String name; 

    public String location; 

    public House() {} 

    public House(String name, String location) { 
     this.name = name; 
     this.location = location; 
    } 
} 

Ora, quando ho serializzare una persona, il XML sarà simile a questo:

<people> 
    <person> 
     <name>Edward</name> 
     <houses> 
      <house> 
       <name>MyAppartment</name> 
       <location>London</location> 
      </house> 
      <house> 
       <name>MySecondAppartment</name> 
       <location>London</location> 
      </house> 
     </houses> 
    </person> 

    <person> 
     <name>Thomas</name> 
     <houses> 
      <house> 
       <name>MyAppartment</name> 
       <location>London</location> 
      </house> 
      <house> 
       <name>MySecondAppartment</name> 
       <location>London</location> 
      </house> 
     </houses> 
    </person> 
</people> 

Il problema qui è che le stesse case sono elencate più volte. Ora aggiungo i decommentato XmlIDREF e XmlID annotazioni, il che porterebbe a XML simile a questo:

<people> 
    <person> 
     <name>Edward</name> 
     <houses> 
      <house>MyAppartment</house> 
      <house>MySecondAppartment</house> 
     </houses> 
    </person> 

    <person> 
     <name>Thomas</name> 
     <houses> 
      <house>MyAppartment</house> 
      <house>MySecondAppartment</house> 
     </houses> 
    </person> 
</people> 

Mentre il primo XML è stato troppo prolisso, questo manca di informazioni. Come posso creare (e unmarshalling) qualcosa di simile a:

<people> 
    <person> 
     <name>Edward</name> 
     <houses> 
      <house>MyAppartment</house> 
      <house>MySecondAppartment</house> 
     </houses> 
    </person> 

    <person> 
     <name>Thomas</name> 
     <houses> 
      <house>MyAppartment</house> 
      <house>MySecondAppartment</house> 
     </houses> 
    </person> 

    <houses> 
     <house> 
      <name>MyAppartment</name> 
      <location>London</location> 
     </house> 
     <house> 
      <name>MySecondAppartment</name> 
      <location>London</location> 
     </house> 
    </houses> 
</people> 

La soluzione deve essere generico perché non voglio scrivere lezioni extra per ogni nuovo elemento nel grafico oggetto.

Per completezza, ecco il webservice riposante:

@Path("rest/persons") 
public class TestService { 
    @GET 
    @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) 
    public Collection<Person> test() throws Exception { 
     Collection<Person> persons = new ArrayList<Person>(); 
     Collection<House> houses = new HashSet<House>(); 
     houses.add(new House("MyAppartment", "London")); 
     houses.add(new House("MySecondAppartment", "London")); 
     persons.add(new Person("Thomas", houses)); 
     persons.add(new Person("Edward", houses)); 
     return persons; 
    } 
} 

Grazie in anticipo.

+1

possibile duplicato di [Can JAXB marshal per contenimento in un primo momento quindi marshal da @XmlIDREF per riferimenti successivi?] (Http://stackoverflow.com/questions/7587095/can-jaxb-marshal-by-containment-at-first -then-marshal-by-xmlidref-per-secondsen) –

+0

Potrei scrivere un '' 'XmlAdapter''' che riconfigura un'istanza superficiale di una sottoclasse' '' Casa''' contenente tutti i valori o solo un riferimento all'originale esempio, sì.Ma ci sono molti svantaggi: (1) dovrei scrivere sottoclassi per ogni classe nel grafo degli oggetti, (2) Dovrei aggiungere tutti '' '@ XmlAttribute''s nel' '' marshal () '' 'and' '' unmarshal() '' 'metodi, e infine (3) non produrrà un XML contenente le case come figli del nodo radice. Ci sono molte cose che dovrei adottare quando si cambia il modello. E tutto ciò potrebbe essere fatto automaticamente poiché tutte le informazioni sono lì. – steffen

risposta

2

Se si sta tentando di serializzare in un formato che corrisponde all'ultimo esempio XML fornito, credo che il grafico dell'oggetto sia strutturato in modo errato per raggiungere tale obiettivo.

Se si desidera fornire una raccolta di oggetti Person con le rispettive case associate e fornire anche una raccolta degli oggetti House, è necessario restituire un messaggio XML serializzato che contenga entrambe le raccolte. Sembra che tu abbia le tue annotazioni @XmlIDREF e @XmlID nel posto giusto per rendere l'associazione Person-House come vuoi (in base alla tua descrizione) ma restituisci solo una collezione degli oggetti Person invece di restituire entrambe le raccolte.

tuo webservice dovrebbe essere più simile a questo (lasciando fuori la serializzazione come appare sei chiaro su come serializzare esso):

@Path("rest/persons") 
public class TestService { 
    @GET 
    @Produces({ MediaType.TEXT_XML, MediaType.APPLICATION_JSON }) 
    public Map<String, Object> test() throws Exception { 
     Map<String, Object> peopleAndHouses = new HashMap<String, Object>(); 
     Collection<Person> persons = new ArrayList<Person>(); 
     Collection<House> houses = new HashSet<House>(); 

     houses.add(new House("MyAppartment", "London")); 
     houses.add(new House("MySecondAppartment", "London")); 
     persons.add(new Person("Thomas", houses)); 
     persons.add(new Person("Edward", houses)); 

     peopleAndHouses.put("houses", houses); 
     peopleAndHouses.put("people", persons); 
     return peopleAndHouses; 
    } 
} 

ci sono altri modi per ottenere questo risultato (ad esempio, creare un oggetto wrapper che ha attributi di raccolta per le persone e le case, ecc.) ma si spera che tu abbia l'idea.

Problemi correlati