JAXB 地图适配器
JAXB Map adapter
我在将 XML 复杂类型转换为 java.util.Map 时遇到问题。解组时,只有值被填充,键变为 NULL。我希望将下面的 XML 转换为 java.util.Map<"user_type","students">
,但它会变成 java.util.Map<NULL,"students">
。有人可以告诉我为什么我得到的密钥为 NULL 吗?
XML
<root>
<myMap>
<user_type>students</user_type>
</myMap>
</root>
POJO
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class MyPojo implements Serializable {
private static final long serialVersionUID = -4589166768649033266L;
@XmlElement(name = "myMap")
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String,String> myMap;
//getters and setters
}
MapAdapter 实现是 http://blog.bdoughan.com/2013/06/moxys-xmlvariablenode-using-maps-key-as.html
@Override
public Map<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
List<AdaptedEntry> adaptedEntries = adaptedMap.entries;
Map<String, String> map = new HashMap<String, String>(adaptedEntries.size());
for(AdaptedEntry adaptedEntry : adaptedEntries) {
map.put(adaptedEntry.key, adaptedEntry.value);
}
return map;
}
我看到的第一个错误是您使用的是 Map<String, Integer>
映射,而您的 XML 具有字符串值。
按如下方式更改您的代码:
public class MapAdapter extends XmlAdapter<MapAdapter.AdaptedMap, Map<String, String>> {
public static class AdaptedMap {
@XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry {
@XmlTransient
public String key;
@XmlValue
public String value;
}
@Override
public AdaptedMap marshal(Map<String, String> map) throws Exception {
AdaptedMap adaptedMap = new AdaptedMap();
for(Entry<String, String> entry : map.entrySet()) {
AdaptedEntry adaptedEntry = new AdaptedEntry();
adaptedEntry.key = entry.getKey();
adaptedEntry.value = entry.getValue();
adaptedMap.entries.add(adaptedEntry);
}
return adaptedMap;
}
@Override
public Map<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
List<AdaptedEntry> adaptedEntries = adaptedMap.entries;
Map<String, String> map = new HashMap<String, String>(adaptedEntries.size());
for(AdaptedEntry adaptedEntry : adaptedEntries) {
map.put(adaptedEntry.key, adaptedEntry.value);
}
return map;
}
}
在您的 MyPojo
class 中,您需要指定需要将哪个 XML 元素映射为 Map
。
@XmlElement(name = "myMap"),
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String,String> myMap;
如果您使用转换框,有两种方法可以做到这一点...(http://capsulesforthejavamind.blogspot.in/2015/01/conversion-box.html)
方式一
将 XML 转换为 Map 并将 Map 设置到 POJO 中。
import java.util.Map;
import cjm.component.cb.map.ToMap;
public class Testing
{
public static void main(String[] args)
{
try
{
String xml = "<root><myMap><user_type>students</user_type></myMap></root>";
System.out.println("XML: " + xml); // your XML
ToMap toMap = new ToMap();
Map<String, Object> map = toMap.convertToMap(xml);
System.out.println("Converted Map: " + map); // converted map
Map<String, Object> rootMap = (Map<String, Object>) map.get("root");
Map<String, String> myMap = (Map<String, String>) rootMap.get("myMap");
System.out.println("My Map: " + myMap); // final map you want);
MyPojo myPojo = new MyPojo();
myPojo.setMyMap(myMap); // map set to the POJO
System.out.println("POJO: " + myPojo);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
输出:
XML: <root><myMap><user_type>students</user_type></myMap></root>
-------- XML Detected --------
-------- Map created Successfully --------
Converted Map: {root={myMap={user_type=students}}}
My Map: {user_type=students}
POJO: MyPojo [myMap={user_type=students}]
方式 2
将 XML 转换为 POJO。但这要求 POJO 完全符合 XML 的结构。因此我创建了一个 Root class 如下:
public class Root
{
private MyPojo myPojo;
public MyPojo getMyPojo()
{
return myPojo;
}
public void setMyPojo(MyPojo myPojo)
{
this.myPojo = myPojo;
}
@Override
public String toString()
{
return "Root [myPojo=" + myPojo + "]";
}
}
我的波乔
import java.io.Serializable;
import java.util.Map;
public class MyPojo implements Serializable
{
private static final long serialVersionUID = -4589166768649033266L;
private Map<String, String> myMap;
public Map<String, String> getMyMap()
{
return myMap;
}
public void setMyMap(Map<String, String> myMap)
{
this.myMap = myMap;
}
@Override
public String toString()
{
return "MyPojo [myMap=" + myMap + "]";
}
}
转化
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cjm.component.cb.object.ToObject;
public class Testing
{
public static void main(String[] args)
{
try
{
String xml = "<root><myMap><user_type>students</user_type></myMap></root>";
System.out.println("XML: " + xml); // your XML
Map<String, String> headerMap = new HashMap<String, String>();
headerMap.put("root", "myPojo"); // header substitutions
List<Object> objectList = new ArrayList<Object>();
objectList.add(new MyPojo()); // since its a nested POJO
ToObject toObject = new ToObject();
Root root = (Root) toObject.convertToObject(xml, new Root(), objectList, headerMap); // conversion to POJO
System.out.println("POJO: " + root);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
输出:
XML: <root><myMap><user_type>students</user_type></myMap></root>
-------- XML Detected --------
-------- XML Detected --------
-------- Map created Successfully --------
-------- Object created Successfully --------
POJO: Root [myPojo=MyPojo [myMap={user_type=students}]]
我在将 XML 复杂类型转换为 java.util.Map 时遇到问题。解组时,只有值被填充,键变为 NULL。我希望将下面的 XML 转换为 java.util.Map<"user_type","students">
,但它会变成 java.util.Map<NULL,"students">
。有人可以告诉我为什么我得到的密钥为 NULL 吗?
XML
<root>
<myMap>
<user_type>students</user_type>
</myMap>
</root>
POJO
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
public class MyPojo implements Serializable {
private static final long serialVersionUID = -4589166768649033266L;
@XmlElement(name = "myMap")
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String,String> myMap;
//getters and setters
}
MapAdapter 实现是 http://blog.bdoughan.com/2013/06/moxys-xmlvariablenode-using-maps-key-as.html
@Override
public Map<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
List<AdaptedEntry> adaptedEntries = adaptedMap.entries;
Map<String, String> map = new HashMap<String, String>(adaptedEntries.size());
for(AdaptedEntry adaptedEntry : adaptedEntries) {
map.put(adaptedEntry.key, adaptedEntry.value);
}
return map;
}
我看到的第一个错误是您使用的是 Map<String, Integer>
映射,而您的 XML 具有字符串值。
按如下方式更改您的代码:
public class MapAdapter extends XmlAdapter<MapAdapter.AdaptedMap, Map<String, String>> {
public static class AdaptedMap {
@XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
public static class AdaptedEntry {
@XmlTransient
public String key;
@XmlValue
public String value;
}
@Override
public AdaptedMap marshal(Map<String, String> map) throws Exception {
AdaptedMap adaptedMap = new AdaptedMap();
for(Entry<String, String> entry : map.entrySet()) {
AdaptedEntry adaptedEntry = new AdaptedEntry();
adaptedEntry.key = entry.getKey();
adaptedEntry.value = entry.getValue();
adaptedMap.entries.add(adaptedEntry);
}
return adaptedMap;
}
@Override
public Map<String, String> unmarshal(AdaptedMap adaptedMap) throws Exception {
List<AdaptedEntry> adaptedEntries = adaptedMap.entries;
Map<String, String> map = new HashMap<String, String>(adaptedEntries.size());
for(AdaptedEntry adaptedEntry : adaptedEntries) {
map.put(adaptedEntry.key, adaptedEntry.value);
}
return map;
}
}
在您的 MyPojo
class 中,您需要指定需要将哪个 XML 元素映射为 Map
。
@XmlElement(name = "myMap"),
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String,String> myMap;
如果您使用转换框,有两种方法可以做到这一点...(http://capsulesforthejavamind.blogspot.in/2015/01/conversion-box.html)
方式一
将 XML 转换为 Map 并将 Map 设置到 POJO 中。
import java.util.Map;
import cjm.component.cb.map.ToMap;
public class Testing
{
public static void main(String[] args)
{
try
{
String xml = "<root><myMap><user_type>students</user_type></myMap></root>";
System.out.println("XML: " + xml); // your XML
ToMap toMap = new ToMap();
Map<String, Object> map = toMap.convertToMap(xml);
System.out.println("Converted Map: " + map); // converted map
Map<String, Object> rootMap = (Map<String, Object>) map.get("root");
Map<String, String> myMap = (Map<String, String>) rootMap.get("myMap");
System.out.println("My Map: " + myMap); // final map you want);
MyPojo myPojo = new MyPojo();
myPojo.setMyMap(myMap); // map set to the POJO
System.out.println("POJO: " + myPojo);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
输出:
XML: <root><myMap><user_type>students</user_type></myMap></root>
-------- XML Detected --------
-------- Map created Successfully --------
Converted Map: {root={myMap={user_type=students}}}
My Map: {user_type=students}
POJO: MyPojo [myMap={user_type=students}]
方式 2
将 XML 转换为 POJO。但这要求 POJO 完全符合 XML 的结构。因此我创建了一个 Root class 如下:
public class Root
{
private MyPojo myPojo;
public MyPojo getMyPojo()
{
return myPojo;
}
public void setMyPojo(MyPojo myPojo)
{
this.myPojo = myPojo;
}
@Override
public String toString()
{
return "Root [myPojo=" + myPojo + "]";
}
}
我的波乔
import java.io.Serializable;
import java.util.Map;
public class MyPojo implements Serializable
{
private static final long serialVersionUID = -4589166768649033266L;
private Map<String, String> myMap;
public Map<String, String> getMyMap()
{
return myMap;
}
public void setMyMap(Map<String, String> myMap)
{
this.myMap = myMap;
}
@Override
public String toString()
{
return "MyPojo [myMap=" + myMap + "]";
}
}
转化
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cjm.component.cb.object.ToObject;
public class Testing
{
public static void main(String[] args)
{
try
{
String xml = "<root><myMap><user_type>students</user_type></myMap></root>";
System.out.println("XML: " + xml); // your XML
Map<String, String> headerMap = new HashMap<String, String>();
headerMap.put("root", "myPojo"); // header substitutions
List<Object> objectList = new ArrayList<Object>();
objectList.add(new MyPojo()); // since its a nested POJO
ToObject toObject = new ToObject();
Root root = (Root) toObject.convertToObject(xml, new Root(), objectList, headerMap); // conversion to POJO
System.out.println("POJO: " + root);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
输出:
XML: <root><myMap><user_type>students</user_type></myMap></root>
-------- XML Detected --------
-------- XML Detected --------
-------- Map created Successfully --------
-------- Object created Successfully --------
POJO: Root [myPojo=MyPojo [myMap={user_type=students}]]