In einem RestFul-Webservice (Jersey) -Kontext muss ich ein Objektdiagramm zu XML und JSON marshalieren/serialisieren. Der Einfachheit halber versuche ich das Problem mit 2-3 Klassen zu erklären:JAXB-serialisiertes XML mit ID-Referenzen statt Containment
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;
}
}
Wenn nun serialisiert ich eine Person, die XML wird so aussehen:
<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>
Das Problem hier ist, dass die gleichen Häuser mehrfach aufgeführt sind. Nun füge ich die uncommented XmlIDREF
und XmlID
Annotationen, die in XML ähnlich wie dies zur Folge hätte:
<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>
Während die erste XML zu ausführlich war, das eine Information fehlt.
<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>
Die Lösung sollte generisch sein, weil ich nicht will zusätzliche Klassen für jedes neues Element im Objektgraphen schreiben: Wie kann ich (und Abstellungs) etwas ähnliches erstellen.
Für Vollständigkeit, hier ist der ruhige webservice:
@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;
}
}
Vielen Dank im Voraus.
mögliche Duplikate von [Kann JAXB marshalen durch Eindämmung zunächst dann Marshal von @XmlIDREF für nachfolgende Referenzen?] (Http://stackoverflow.com/questions/7587095/can-jaxb-marshal-by-containment-at-first -then-marshal-by-xmlidref-for-subsequences) –
Ich könnte ein '' 'XmlAdapter''' schreiben, das eine oberflächliche Instanz eines untergeordneten' '' House''' zurückgibt, die alle Werte enthält oder nur auf das Original verweist Beispiel, ja.Aber es gibt viele Nachteile: (1) Ich müsste für jede Klasse im Objektgraphen Unterklassen schreiben, (2) Ich müsste alle '' @ XmlAttribute'''s im '' Marshal () '' '' und '' 'unmarshal()' '' Methoden und schließlich (3) wird kein XML erzeugt, das die Häuser als Kinder des Wurzelknotens enthält. Es gibt viele Dinge, die ich übernehmen müsste, wenn ich das Modell ändere. Und das alles kann automatisch erledigt werden, da alle Informationen vorhanden sind. – steffen