J'ai plusieurs structures de données complexes commeJAXB: Comment rassembler des structures de données imbriquées complexes?
Map< A, Set<B> >
Set< Map< A, B > >
Set< Map< A, Set<B> > >
Map< A, Map< B, Set<C> > >
and so on (more complex data structures)
Note: Dans mon cas, il n'a pas vraiment d'importance si j'utiliser ensemble ou une liste.
Maintenant, je sais que JAXB permettez-moi de définir « s XMLAdapter, c'est très bien, mais je ne veux pas définir un XMLAdapter pour toutes les structures de données fournies (il serait juste trop d'auteur et-coller le code).
J'ai essayé d'atteindre mon objectif en déclarant deux XmlAdapters généralisantes:
- une pour Carte:
MapAdapter<K,V>
- un pour Set:
SetAdapter<V>
Le problème:
se plaint JAXB comme suit:
javax.xml.bind.JAXBException:
class java.util.Collections$UnmodifiableMap nor any of its
super class is known to this context.
Voici ma classe d'adaptateur:
import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;
public class Adapters {
public final static class MapAdapter<K, V>
extends XmlAdapter<MapAdapter.Adapter<K, V>, Map<K, V>> {
@XmlType
@XmlRootElement
public final static class Adapter<K, V> {
@XmlElement
protected List<MyEntry<K, V>> key = new LinkedList<MyEntry<K, V>>();
private Adapter() {
}
public Adapter(Map<K, V> original) {
for (Map.Entry<K, V> entry : original.entrySet()) {
key.add(new MyEntry<K, V>(entry));
}
}
}
@XmlType
@XmlRootElement
public final static class MyEntry<K, V> {
@XmlElement
protected K key;
@XmlElement
protected V value;
private MyEntry() {
}
public MyEntry(Map.Entry<K, V> original) {
key = original.getKey();
value = original.getValue();
}
}
@Override
public Adapter<K, V> marshal(Map<K, V> obj) {
return new Adapter<K, V>(obj);
}
@Override
public Map<K, V> unmarshal(Adapter<K, V> obj) {
throw new UnsupportedOperationException("unmarshalling is never performed");
}
}
}
Voici mon cas de test JUnit:
import java.io.*;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;
import org.junit.*;
import static java.lang.System.*;
public class SomeTest {
@Test
public void _map2()
throws Exception {
Map<String, Map<String, String>> dataStructure =
new HashMap<String, Map<String, String>>();
Map<String, String> inner1 = new HashMap<String, String>();
Map<String, String> inner2 = new HashMap<String, String>();
dataStructure.put("a", inner1);
dataStructure.put("b", inner1);
inner1.put("a1", "1");
inner1.put("a2", "2");
inner2.put("b1", "1");
inner2.put("b2", "2");
JAXBContext context = JAXBContext.newInstance(Adapters.XMap.class,
Adapters.XCount.class, Adapters.XEntry.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setAdapter(new Adapters.MapAdapter());
StringWriter sw = new StringWriter();
marshaller.marshal(dataStructure, sw);
out.println(sw.toString());
}
}
Cool! Il se peut que je doive le faire moi-même un jour. Pourriez-vous également publier un résumé de ce que vous deviez faire dans votre fichier de liaison .xjb? –
Je n'ai jamais utilisé le fichier de liaison .xjb;) La solution proposée fonctionne juste;) –
Je devais ajouter '@XmlSeeAlso ({Adapters.XMap.class, Adapters.XCollection.class, Adapters.XEntry.class}) 'sur ma classe annotée JAXB pour que cela fonctionne. – ajitomatix