我使用JDK7和Jaxb
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.7</version>
</dependency>
我想按照以下方式编组地图:
<options>
<key> VALUE </key>
<key2> VALUE2 </key2>
...
</options>
所以我试试这个:
@XmlRootElement
public class Preferences {
@XmlJavaTypeAdapter(OptionsMapAdapter.class)
private Map<String, String> options;
}
public class OptionsMapAdapter extends XmlAdapter<OptionsMapAdapter.OptionsWrapper, Map<String, String>> {
@Override
public Map<String, String> unmarshal(final OptionsWrapper value) throws Exception {
final Map<String, String> options = new HashMap<>();
for (JAXBElement<String> option : value.options) {
options.put(option.getName().toString(), option.getValue());
}
return options;
}
@Override
public OptionsWrapper marshal(final Map<String, String> value) throws Exception {
OptionsWrapper wrapper = new OptionsWrapper();
for (Map.Entry<String, String> property : value.entrySet()) {
wrapper.options.add(new JAXBElement<>(
new QName(property.getKey()),
String.class, property.getValue()));
}
return wrapper;
}
static class OptionsWrapper {
@XmlAnyElement(lax = true)
public List<JAXBElement<String>> options = new ArrayList<>();
}
}
它在 marshall 上运行良好,但在 unmarshall 上失败并显示错误:
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl无法强制转换为 javax.xml.bind.JAXBElement
在调试中我看到,在OptionsMapAdapter#unmarshal上,OptionsWrapper.options列表不包含JAXBElement列表,但列出了com.sun.org.apache.xerces.internal.dom.ElementNSImpl。
这是一个错误,如何纠正问题(没有取消列表选项的分类)? 如果松懈或没有松懈,就会出现同样的问题。
答案 0 :(得分:1)
适配器的这个修改版本适用于编组和解组(1.8.0_20)。
public class OptionsMapAdapter
extends XmlAdapter<OptionsMapAdapter.OptionsWrapper, Map<String, String>> {
static Document document;
static {
try { document =
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
} catch( Exception e ){
// error handling
}
}
@Override
public Map<String, String> unmarshal(final OptionsWrapper value) throws Exception {
final Map<String, String> options = new HashMap<>();
for (Element option : value.options) {
options.put(option.getTagName(), option.getTextContent());
}
return options;
}
@Override
public OptionsWrapper marshal(final Map<String, String> value) throws Exception {
OptionsWrapper wrapper = new OptionsWrapper();
for (Map.Entry<String, String> property : value.entrySet()) {
Element element = document.createElement(property.getKey() );
element.setTextContent( property.getValue() );
wrapper.options.add( element );
}
return wrapper;
}
static class OptionsWrapper {
@XmlAnyElement(lax = true)
public List<Element> options = new ArrayList<>();
}
}
org.w3c.dom.Element
比JAXBElement稍微方便,但它会影响适配器。