私はいくつかの複雑なデータ構造を持っています
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)
注:私の場合、SetとListのどちらを使用してもかまいません。
これで、JAXBでXmlAdapterを定義できることがわかりました。これで問題ありませんが、指定されたすべてのデータ構造に対してXmlAdapterを定義したくありません(コピーアンドペーストコードが多すぎます)。
私は2つの一般化XmlAdaptersを宣言することによって私の目標を達成しようとしました:
- マップ用に1つ:
MapAdapter<K,V>
- セット用に1つ:
SetAdapter<V>
問題:
JAXBは次のように文句を言います:
javax.xml.bind.JAXBException:
class java.util.Collections$UnmodifiableMap nor any of its
super class is known to this context.
これが私のアダプタクラスです:
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");
}
}
}
これが私の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());
}
}