java - 编码映射到 <key>value</key> 失败

标签 java jaxb2

我使用 JDK7 和 Jaxb

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.7</version>
</dependency>

我想按如下方式编码 map :

<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<>();
    }
}

它在 ma​​rshall 上工作正常,但在 unmarshall 上失败并出现错误:

java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to javax.xml.bind.JAXBElement

在调试时,我看到在 OptionsMapAdapter#unmarshal 上,OptionsWrapper.options 列表不包含 JAXBElement 列表,而是包含 com.sun.org.apache.xerces.internal.dom.ElementNSImpl 列表。

这是一个错误,如何解决这个问题(不取消输入列表选项)? 有 lax 或没有 lax 都有同样的问题。

最佳答案

此适配器的修改变体适用于编码和解码 (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 方便,但它只影响适配器。

关于java - 编码映射到 <key>value</key> 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27650107/

相关文章:

java - 为什么每次在 MS Word 中再次保存文件时,Java 中的 .doc 或 .docx 文件的字节数组都会发生变化?

marshalling - 如何为 JAXB 2.0 编码编写单元测试

java - 如何使用 Jax-RS 返回 Java List<String> Json

mapping - 我可以为 java.util.Map 自定义 JAXB @XmlElementWrapper 元素吗

java - JDBC 返回空结果集,但记录存在于数据库中

java - 如何打印对象的实现类

java - 如何为第三方应用程序创建连接池/仅一次?

java - GWT 按钮 onClick() 返回一个值

java - 解码后返回 null 和空 List

java - org.springframework.oxm.jaxb.Jaxb2Marshaller 元音变音和特殊字符