JAXB 将未定义的元素解组到 Map?
JAXB unmarshal undefined elements to Map?
我有一个XML要解组:
<?xml version="1.0" encoding="UTF-8"?>
<ROW id='1'>
<MOBILE>9831138683</MOBILE>
<A>1</A>
<B>2</B>
</ROW>
我想把它映射到 class:
import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ROW {
@XmlPath(".")
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String, Integer> map = new HashMap<String, Integer>();
@XmlAttribute
private int id;
@XmlElement(name = "MOBILE")
private int mobileNo;
}
为此,我尝试了 bdoughan 博客,其中使用 @XmlVariableNode("key")
:
地图适配器:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlVariableNode;
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;
}
}
使用这种方法,所有键 (MOBILE, id, A, B
) 都映射到 Map
内。我想解组以便所有定义的属性 id
、MOBILE
都映射到它们在 POJO 中的属性,其余的都映射到 Map
.
如何实现?
我有一个解决方案,但与您上面尝试的略有不同。
让我们根class:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ROW")
public class Row {
@XmlAttribute
private int id;
@XmlElement(name = "MOBILE")
private int mobileNo;
@XmlMixed
@XmlAnyElement
@XmlJavaTypeAdapter(MyMapAdapter.class)
private Map<String, String> otherElements;
}
以及将未知值转换为映射的适配器:
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilderFactory;
import java.util.HashMap;
import java.util.Map;
public class MyMapAdapter extends XmlAdapter<Element, Map<String, String>> {
private Map<String, String> hashMap = new HashMap<>();
@Override
public Element marshal(Map<String, String> map) throws Exception {
// expensive, but keeps the example simpler
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = document.createElement("dynamic-elements");
for(Map.Entry<String, String> entry : map.entrySet()) {
Element element = document.createElement(entry.getKey());
element.setTextContent(entry.getValue());
root.appendChild(element);
}
return root;
}
@Override
public Map<String, String> unmarshal(Element element) {
String tagName = element.getTagName();
String elementValue = element.getChildNodes().item(0).getNodeValue();
hashMap.put(tagName, elementValue);
return hashMap;
}
}
这会将 id 和手机号码放在字段中,其余的,未知的进入地图。
编组将不会与您显示的 xml 完全相同。它在动态值周围放置了一个包装器,看起来像这样:
<ROW id="1">
<MOBILE>1241204091</MOBILE>
<dynamic-elements>
<A>1</A>
<B>2</B>
</dynamic-elements>
</ROW>
我有一个XML要解组:
<?xml version="1.0" encoding="UTF-8"?>
<ROW id='1'>
<MOBILE>9831138683</MOBILE>
<A>1</A>
<B>2</B>
</ROW>
我想把它映射到 class:
import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ROW {
@XmlPath(".")
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String, Integer> map = new HashMap<String, Integer>();
@XmlAttribute
private int id;
@XmlElement(name = "MOBILE")
private int mobileNo;
}
为此,我尝试了 bdoughan 博客,其中使用 @XmlVariableNode("key")
:
地图适配器:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlVariableNode;
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;
}
}
使用这种方法,所有键 (MOBILE, id, A, B
) 都映射到 Map
内。我想解组以便所有定义的属性 id
、MOBILE
都映射到它们在 POJO 中的属性,其余的都映射到 Map
.
如何实现?
我有一个解决方案,但与您上面尝试的略有不同。
让我们根class:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "ROW")
public class Row {
@XmlAttribute
private int id;
@XmlElement(name = "MOBILE")
private int mobileNo;
@XmlMixed
@XmlAnyElement
@XmlJavaTypeAdapter(MyMapAdapter.class)
private Map<String, String> otherElements;
}
以及将未知值转换为映射的适配器:
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.parsers.DocumentBuilderFactory;
import java.util.HashMap;
import java.util.Map;
public class MyMapAdapter extends XmlAdapter<Element, Map<String, String>> {
private Map<String, String> hashMap = new HashMap<>();
@Override
public Element marshal(Map<String, String> map) throws Exception {
// expensive, but keeps the example simpler
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = document.createElement("dynamic-elements");
for(Map.Entry<String, String> entry : map.entrySet()) {
Element element = document.createElement(entry.getKey());
element.setTextContent(entry.getValue());
root.appendChild(element);
}
return root;
}
@Override
public Map<String, String> unmarshal(Element element) {
String tagName = element.getTagName();
String elementValue = element.getChildNodes().item(0).getNodeValue();
hashMap.put(tagName, elementValue);
return hashMap;
}
}
这会将 id 和手机号码放在字段中,其余的,未知的进入地图。
编组将不会与您显示的 xml 完全相同。它在动态值周围放置了一个包装器,看起来像这样:
<ROW id="1">
<MOBILE>1241204091</MOBILE>
<dynamic-elements>
<A>1</A>
<B>2</B>
</dynamic-elements>
</ROW>