JAXB:我应该如何封送复杂的嵌套数据结构?

我有几种复杂的数据结构,例如

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(这将是太多的复制和粘贴代码)。

我试图通过声明两个泛化的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");

}

}

}

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());

}

}

回答:

我已经解决了 问题。

我已经为 , 和 编写了带有JAXB注释的对象。

主要思想是在 方法内部:

看一下代码:

public final class Adapters {

private Adapters() {

}

public static Class<?>[] getXmlClasses() {

return new Class<?>[]{

XMap.class, XEntry.class, XCollection.class, XCount.class

};

}

public static Object xmlizeNestedStructure(Object input) {

if (input instanceof Map<?, ?>) {

return xmlizeNestedMap((Map<?, ?>) input);

}

if (input instanceof Collection<?>) {

return xmlizeNestedCollection((Collection<?>) input);

}

return input; // non-special object, return as is

}

public static XMap<?, ?> xmlizeNestedMap(Map<?, ?> input) {

XMap<Object, Object> ret = new XMap<Object, Object>();

for (Map.Entry<?, ?> e : input.entrySet()) {

ret.add(xmlizeNestedStructure(e.getKey()),

xmlizeNestedStructure(e.getValue()));

}

return ret;

}

public static XCollection<?> xmlizeNestedCollection(Collection<?> input) {

XCollection<Object> ret = new XCollection<Object>();

for (Object entry : input) {

ret.add(xmlizeNestedStructure(entry));

}

return ret;

}

@XmlType

@XmlRootElement

public final static class XMap<K, V> {

@XmlElementWrapper(name = "map")

@XmlElement(name = "entry")

private List<XEntry<K, V>> list = new LinkedList<XEntry<K, V>>();

public XMap() {

}

public void add(K key, V value) {

list.add(new XEntry<K, V>(key, value));

}

}

@XmlType

@XmlRootElement

public final static class XEntry<K, V> {

@XmlElement

private K key;

@XmlElement

private V value;

private XEntry() {

}

public XEntry(K key, V value) {

this.key = key;

this.value = value;

}

}

@XmlType

@XmlRootElement

public final static class XCollection<V> {

@XmlElementWrapper(name = "list")

@XmlElement(name = "entry")

private List<V> list = new LinkedList<V>();

public XCollection() {

}

public void add(V obj) {

list.add(obj);

}

}

}

让我们看一个 :

<xMap>

<map>

<entry>

<key xsi:type="xCount" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<count>1</count>

<content xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">a</content>

</key>

<value xsi:type="xCollection" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<list>

<entry xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">a1</entry>

<entry xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">a2</entry>

<entry xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">a3</entry>

</list>

</value>

</entry>

<entry>

<key xsi:type="xCount" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<count>2</count>

<content xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">b</content>

</key>

<value xsi:type="xCollection" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<list>

<entry xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">b1</entry>

<entry xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">b3</entry>

<entry xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">b2</entry>

</list>

</value>

</entry>

<entry>

<key xsi:type="xCount" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<count>3</count>

<content xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">c</content>

</key>

<value xsi:type="xCollection" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

<list>

<entry xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">c1</entry>

<entry xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">c2</entry>

<entry xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema">c3</entry>

</list>

</value>

</entry>

</map>

</xMap>

抱歉,演示输出还使用了称为 的数据结构,该数据结构 在适配器的源代码中未提及。

有谁知道如何删除所有这些烦人的(对于我而言)不必要的 属性?

以上是 JAXB:我应该如何封送复杂的嵌套数据结构? 的全部内容, 来源链接: utcz.com/qa/403249.html

回到顶部