java.util.Map is an interface, and JAXB can't handle interfaces 解决方法,java.util.mapjaxb,如果在类中定义了接口类型
分享于 点击 12776 次 点评:233
java.util.Map is an interface, and JAXB can't handle interfaces 解决方法,java.util.mapjaxb,如果在类中定义了接口类型
如果在类中定义了接口类型,然后去序列化时会出现标题的异常,堆栈如下:
Exception in thread "main" javax.xml.bind.DataBindingException: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptionsJAXB annotation is placed on a method that is not a JAXB property this problem is related to the following location: at @javax.xml.bind.annotation.XmlTransient() at cn.outofmemory.stable.STableMgrjava.util.Map is an interface, and JAXB can't handle interfaces. this problem is related to the following location: at java.util.Map at public java.util.Map cn.outofmemory.stable.STableMgr.getsTables() at cn.outofmemory.stable.STableMgrjava.util.Map does not have a no-arg default constructor. this problem is related to the following location: at java.util.Map at public java.util.Map cn.outofmemory.stable.STableMgr.getsTables() at cn.outofmemory.stable.STableMgr at javax.xml.bind.JAXB._marshal(JAXB.java:549) at javax.xml.bind.JAXB.marshal(JAXB.java:307) at cn.outofmemory.stable.STableMgr.main(STableMgr.java:53)Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions.....
要解决这个问题需要自定义XmlAdapter,假定我们要序列化的类如下,该类有一个Map的属性。
package cn.outofmemory.stable;import java.io.File;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.xml.bind.JAXB;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlRootElement;import javax.xml.bind.annotation.XmlTransient;import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;import cn.outofmemory.pojo.Table;@XmlRootElementpublic class STableMgr { private Map<String, List<Table>> sTables; @XmlElement(name="sTableMap") @XmlJavaTypeAdapter(MapAdapter.class) public Map<String, List<Table>> getsTables() { return sTables; } public void setsTables(Map<String, List<Table>> sTables) { this.sTables = sTables; } public boolean hasMTable(String srcTableName) { if (this.sTables == null) { return false; } String lowerCase = srcTableName.toLowerCase(); return this.sTables.containsKey(lowerCase); } public List<Table> getTables (String srcTableName) { return this.sTables.get(srcTableName.toLowerCase()); } public static void main (String[] args) { STableMgr instance = new STableMgr(); Map<String, List<Table>> tableMap = new HashMap<String, List<Table>>(); List<Table> tables = new ArrayList<Table>(); tables.add(new Table()); tableMap.put("testSrcTableKey", tables); tableMap.put("testSrcTableKeyq", tables); instance.setsTables(tableMap); String tableListPath = "d:\\s-tables.xml"; File tableMgrSaveAsFile = new File(tableListPath); JAXB.marshal(instance, tableMgrSaveAsFile); }}
需要自己实现的Map接口的XmlAdapter实现如下:
package cn.outofmemory.stable;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlElementWrapper;import javax.xml.bind.annotation.XmlTransient;import javax.xml.bind.annotation.XmlType;import javax.xml.bind.annotation.adapters.XmlAdapter;import cn.outofmemory.pojo.Table;public class MapAdapter extends XmlAdapter<MapAdapter.Converter, Map<String, List<Table>>> { @XmlType(name = "Converter") @XmlAccessorType(XmlAccessType.FIELD) public static class Converter { @XmlTransient private List<MapEntry> entries = new ArrayList<MapEntry>(); public void addEntry(MapEntry entry) { entries.add(entry); } // @XmlElementWrapper(name = "tableMaps") @XmlElement(name = "entry") public List<MapEntry> getEntries() { return entries; } public static class MapEntry { private String key; private List<Table> value; public MapEntry() { super(); } public MapEntry(Map.Entry<String, List<Table>> entry) { super(); this.key = entry.getKey(); this.value = entry.getValue(); } public MapEntry(String key, List<Table> value) { super(); this.key = key; this.value = value; } @XmlElement(name="srcTableName") public String getKey() { return key; } public void setKey(String key) { this.key = key; } @XmlElementWrapper(name = "sTables") @XmlElement(name = "table") public List<Table> getValue() { return value; } public void setValue(List<Table> value) { this.value = value; } } } @Override public Map<String, List<Table>> unmarshal(Converter v) throws Exception { Map<String, List<Table>> result = new HashMap<String, List<Table>>(); for (Converter.MapEntry e : v.getEntries()) { result.put(e.getKey(), e.getValue()); } return result; } @Override public Converter marshal(Map<String, List<Table>> map) throws Exception { Converter convertor = new Converter(); for (Map.Entry<String, List<Table>> entry : map.entrySet()) { Converter.MapEntry e = new Converter.MapEntry(entry); convertor.addEntry(e); } return convertor; }}
通过自定义的MapAdapter就可以正常的使用jaxb序列化Map接口类型了。
用户点评