# JAXB - Generischen Wert mit Liste belegen



## LoadingByte (9. Mrz 2014)

Hallo erstmal,

das Problem ist dieses: Ich habe eine (in diesem Fall stark verkürzte) Klasse Payload:


```
@XmlRootElement
private static class Payload<T> {

    @XmlElement
    private T value;

}
```

Wenn ich das Attribut "value" einer Instanz dieser Klasse z.B. mit einem String fülle, der bei JAXB Out-of-the-Box dabei ist, und dann marshalle, bekomme ich ein korrektes Ergebnis:

[XML]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<payload>
    <value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Test</value>
</payload>
[/XML]

Mit Arrays und eigenen Typen funktioniert das auch noch.

Wenn ich aber eine Liste als "value" verwende:


```
Payload<List<String>> payload = new Payload<List<String>>();
payload.value = new ArrayList<String>();
// Liste füllen ...

JAXBContext context = JAXBContext.newInstance(Payload.class, ArrayList.class); // ArrayList muss registriert werden, da JAXB die Liste offensichtlich nicht erkennen kann
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter serialized = new StringWriter();
marshaller.marshal(payload, serialized);
System.out.println(serialized);
```

Dann bekomme ich folgendes Ergebnis:

[XML]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<payload>
    <value xsi:type="arrayList" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</payload>
[/XML]

Wie offensichtlich sein sollte, wird die ArrayList als normaler Typ dargestellt, und JAXBs Methode zum marshallen von Collections greift icht.

Meine Frage: Gibt es eine Möglichkeit, dass JAXB auch Listen im "Payload" richtig serialisiert?


----------



## LoadingByte (9. Mrz 2014)

So, ich habe mich nochmal überlegt; als Workaround würde auch ein Adapter dienen.
Dabei wird der Adapter an das generische Element angeheftet:


```
@XmlRootElement
private static class Payload<T> {

    @XmlElement
    @XmlJavaTypeAdapter (CollectionAdapter.class)
    private T value;

}
```

Ohne Getter und Setter würde der Adapter dann so aussehen:


```
public class CollectionAdapter extends XmlAdapter<Object, Object> {

    public CollectionAdapter() {

    }

    @Override
    public Object unmarshal(Object object) {

        return object;
    }

    @Override
    public Object marshal(Object object) {

        if (object instanceof Collection) {
            CollectionWrapper wrapper = new CollectionWrapper();
            wrapper.collection = (Collection<?>) object;
            return wrapper;
        }

        return object;

    }

    @XmlType (name = "collection")
    public static class CollectionWrapper {

        @XmlElement (name = "item")
        private Collection<?> collection;

    }

}
```

Falls es sich bei dem zu serialisierenden Objekt um eine Collection handelt, wird diese einfach in einen CollectionWrapper gepackt, der JAXB sagt, dass in der Tat eine Collection zu serialisieren ist. Dadurch kann JAXB die Collection-Methode anwenden und die Collection richtig ausgeben:

[XML]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<payload>
    <value xsi:type="collection" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <item xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">Test1</item>
        <item xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">Test2</item>
        <item xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">Test3</item>
    </value>
</payload>
[/XML]

Sieht alles nicht so schön aus, deswegen wäre ich doch schon gespannt, ob es bessere Lösungen gibt.


----------

