JAXB:我应该如何封送复杂的嵌套数据结构?
2022-09-01 09:58:38
我有几个复杂的数据结构,如
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(这将是太多的复制和粘贴代码)。
我试图通过声明两个泛化 XmlAdapters 来实现我的目标:
- 一个用于地图:
MapAdapter<K,V>
- 一个用于设置:
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());
}
}