2012-11-21 17 views
6

W kontekście RestFul-Webservice (Jersey) potrzebuję przygotować/uszeregować wykres Object do XML i JSON. Dla uproszczenia staram się wyjaśnić problem z 2-3 klas:Serializowany XML JAXB z odniesieniami ID, a nie ograniczeniami

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

Teraz kiedy serializacji danej osoby XML będzie wyglądał następująco:

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

Problem polega na tym, że te same domy są wymienione wiele razy. Teraz dodam odkomentowane XmlIDREF i XmlID adnotacje, co powodowałoby XML podobny do tego:

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

ile pierwszy był zbyt gadatliwy XML, ten brak informacji. Jak mogę stworzyć (i unmarshal) coś podobnego do:

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

Roztwór powinien mieć charakter ogólny, ponieważ nie chcę pisać dodatkowe zajęcia dla każdego nowego elementu wykresu obiektu.

Dla kompletności, tutaj jest spokojny usługa:

@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; 
    } 
} 

góry dzięki.

+1

prawdopodobny duplikat [Czy JAXB marszałek przez powstrzymanie na początku następnie marszałek przez @XmlIDREF dla kolejnych odniesień?] (Http://stackoverflow.com/questions/7587095/can-jaxb-marshal-by-containment-at-first -then-marshal-by-xmlidref-for-subshen) –

+0

Mógłbym napisać '' 'XmlAdapter''', który poprawia płytkie wystąpienie podklasy" '' 'House''' zawierającej wszystkie wartości lub tylko odniesienie do oryginału przykład, tak.Ale jest wiele wad: (1) Musiałbym napisać podklasy dla każdej klasy na wykresie obiektu, (2) Musiałbym dodać wszystkie '' '@ XmlAttribute''' w' '' marshal () '' i '' 'unmarshal()' '' metody, a na końcu (3) nie będzie produkować XML zawierających domy jako dzieci węzła głównego. Jest wiele rzeczy, którymi musiałbym się zająć przy zmianie modelu. A wszystko to można zrobić automatycznie, ponieważ wszystkie informacje tam są. – steffen

Odpowiedz

2

Jeśli próbujesz przekształcić do postaci szeregowej, która pasuje do ostatnio podanego przykładu XML, to uważam, że Twój wykres obiektowy ma niepoprawną strukturę, aby to osiągnąć.

Jeśli chcesz udostępnić kolekcję obiektów Person wraz ze skojarzonymi z nimi obiektami, a także dostarczyć kolekcję obiektów House, musisz zwrócić zserializowaną wiadomość XML, która zawiera obie kolekcje. Wygląda na to, że masz adnotacje w odpowiednim miejscu, aby utworzyć skojarzenie Person-House, tak jak zamierzałeś (na podstawie Twojego opisu), ale zwracasz tylko kolekcję obiektów Person, a nie zwracasz obie kolekcje.

Twoja usługa powinna wyglądać mniej więcej tak (pomijając serializacji jak wydaje się, że jesteś jasne, w jaki sposób je szeregować):

@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; 
    } 
} 

Istnieją inne sposoby, aby tego dokonać (np utworzyć obiekt otoki który ma atrybuty kolekcji dla ludzi i domów, itp.), ale mam nadzieję, że wpadniesz na ten pomysł.

Powiązane problemy