本文介绍了JAXB Marshall是泛型类型的Map结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
按照Blaise Doughan的这个例子(http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html),我试图将它推广到使用泛型的任何类型。
我获得:
Following this example (http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html) of Blaise Doughan that works, i am trying to generalize it to any type using generics.I obtained :
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MyMapType<K, V> {
public List<MyMapEntryType<K, V>> entry;
public MyMapType() {
entry = new ArrayList<MyMapEntryType<K, V>>();
}
}
和
import javax.xml.bind.annotation.*;
public class MyMapEntryType<K, V> {
@XmlAttribute
public K key;
@XmlValue
public V value;
}
然后,
import java.util.*;
import java.util.Map.Entry;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public final class MyMapAdapter<K, V> extends
XmlAdapter<MyMapType<K, V>, Map<K, V>> {
@Override
public MyMapType<K, V> marshal(Map<K, V> arg0) throws Exception {
MyMapType<K, V> myMapType = new MyMapType<K, V>();
for (Entry<K, V> entry : arg0.entrySet()) {
MyMapEntryType<K, V> myMapEntryType = new MyMapEntryType<K, V>();
myMapEntryType.key = entry.getKey();
myMapEntryType.value = entry.getValue();
myMapType.entry.add(myMapEntryType);
}
return myMapType;
}
@Override
public Map<K, V> unmarshal(MyMapType<K, V> arg0) throws Exception {
HashMap<K, V> hashMap = new HashMap<K, V>();
for (MyMapEntryType<K, V> myEntryType : arg0.entry) {
hashMap.put(myEntryType.key, myEntryType.value);
}
return hashMap;
}
}
最后,
package forum832656;
import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo<K, V> {
@XmlJavaTypeAdapter(MyMapAdapter.class)
Map<K, V> map = new HashMap<K, V>();
public Foo() {
}
public Map<K, V> getMap() {
return map;
}
public void setMap(Map<K, V> map) {
this.map = map;
}
}
然后我试了这个,
Foo<Integer,String> f = new Foo<Integer,String>();
f.getMap().put(1, "HELLO");
f.getMap().put(2, "WORLD");
JAXBContext context = JAXBContext.newInstance(Foo.class,MyMapType.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(f, System.out);
但我在JAXBContext创建行上获得了NullPointerException ....
有什么想法?
But i obtained a NullPointerException on JAXBContext creation line....Any idea?
推荐答案
我用递归适配器解决了这个问题:
I solved this with a recursive Adapter:
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class MapAdapter<K, V> extends XmlAdapter<Adapter<K, V>, Map<K, V>> {
@Override
public Map<K, V> unmarshal(Adapter<K, V> v) throws Exception {
if (v == null) {
return null;
}
Map<K, V> map = new HashMap<K, V>();
for (MyEntry<K, V> mapEntryType : v.getEntries()) {
map.put(rUnmarshal(mapEntryType.getKey()), rUnmarshal(mapEntryType.getValue()));
}
return map;
}
@Override
public Adapter<K, V> marshal(Map<K, V> v) throws Exception {
if (v == null) {
return null;
}
return new Adapter<K, V>(v);
}
@SuppressWarnings("unchecked")
private static <T> T rUnmarshal(T obj) throws Exception {
if (obj instanceof Adapter) {
return (T) new MapAdapter<>().unmarshal((Adapter<Object, Object>) obj);
}
return obj;
}
@SuppressWarnings("unchecked")
static <T> T rMarshal(T obj) throws Exception {
if (obj instanceof Map) {
return (T) new MapAdapter<>().marshal((Map<Object, Object>) obj);
}
return obj;
}
@XmlType
@XmlRootElement
public final static class Adapter<K, V> {
@XmlElement
protected List<MyEntry<K, V>> fEntries = new LinkedList<MyEntry<K, V>>();
// needed for JAXB
@SuppressWarnings("unused")
private Adapter() {
}
public Adapter(Map<K, V> original) throws Exception {
for (Map.Entry<K, V> entry : original.entrySet()) {
this.fEntries.add(new MyEntry<K, V>(entry));
}
}
public List<MyEntry<K, V>> getEntries() {
return this.fEntries;
}
}
@XmlType
@XmlRootElement
public final static class MyEntry<K, V> {
@XmlElement
protected K fKey;
@XmlElement
protected V fValue;
// needed for JAXB
@SuppressWarnings("unused")
private MyEntry() {
}
public MyEntry(Map.Entry<K, V> original) throws Exception {
this.fKey = rMarshal(original.getKey());
this.fValue = rMarshal(original.getValue());
}
public K getKey() {
return this.fKey;
}
public V getValue() {
return this.fValue;
}
}
}
这应该避免你的NPE。
This should avoid your NPE.
这篇关于JAXB Marshall是泛型类型的Map结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!