JAXB编组由XmlAdapter创建一个ArrayList [英] JAXB marshal an ArrayList created by XmlAdapter

查看:174
本文介绍了JAXB编组由XmlAdapter创建一个ArrayList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用 XmlAdapter 来适应的HashMap 字段的XML重新presentation。我使用的ArrayList 来做到这一点。然而,编组 ArrayList的时候未整理的。这是为什么?

在code

  @XmlRootElement
公共类Foo {    私人的HashMap<字符串,字符串> HashMap的;    公共美孚(){
        this.hashMap =新的HashMap<字符串,字符串>();
    }    @XmlJavaTypeAdapter(HashMapAdapter.class)
    公众的HashMap<字符串,字符串> getHashmap(){
        返回的HashMap;
    }    公共无效setHashmap(HashMap的<字符串,字符串>的HashMap){
        this.hashMap = HashMap的;
    }}

公共最后一类HashMapAdapter扩展XmlAdapter< ArrayList的< HashMapEntry>中的HashMap<字符串,字符串>> {    @覆盖
    公众的ArrayList< HashMapEntry>元帅(HashMap的<字符串,字符串> arg0中)抛出异常{
        ArrayList的< HashMapEntry>结果=新的ArrayList< HashMapEntry>();
        对于(进入<字符串,字符串>项:arg0.entrySet())
            result.add(新HashMapEntry(entry.getKey(),entry.getValue()));
        返回结果;
    }    @覆盖
    公众的HashMap<字符串,字符串>解组(ArrayList的< HashMapEntry> arg0中)抛出异常{
        HashMap的<字符串,字符串>结果=新的HashMap<字符串,字符串>();
        对于(HashMapEntry项:为arg0)
            result.put(entry.key,entry.value);
        返回结果;
    }}

公共类HashMapEntry {    @XmlElement
    公共字符串键;    @XmlValue
    公共字符串值;    公共HashMapEntry(){    }    公共HashMapEntry(字符串键,字符串值){
        this.key =键;
        THIS.VALUE =价值;
    }
}

结果

<?XML版本=1.0编码=UTF-8独立=YES>&LT ;富>< HashMap中/>< / foo的>


解决方案

在你的 XmlAdapter 你需要转换的的HashMap 来使用列表属性,而不是直接到对象的实例的ArrayList

HashMapAdapter

 包forum13163430;进口的java.util。*;
进口java.util.Map.Entry;导入javax.xml.bind.annotation *。
进口javax.xml.bind.annotation.adapters.XmlAdapter;公共final类HashMapAdapter扩展XmlAdapter< HashMapAdapter.AdaptedHashMap,HashMap的<字符串,字符串>> {    @覆盖
    公共AdaptedHashMap元帅(HashMap的<字符串,字符串>的HashMap)抛出异常{
        AdaptedHashMap adaptedHashMap =新AdaptedHashMap();
        对于(进入<字符串,字符串>项:hashMap.entrySet()){
            adaptedHashMap.item.add(新HashMapEntry(entry.getKey(),entry.getValue()));
        }
        返回adaptedHashMap;
    }    @覆盖
    公众的HashMap<字符串,字符串>解组(AdaptedHashMap adaptedHashMap)抛出异常{
        HashMap的<字符串,字符串>结果=新的HashMap<字符串,字符串>();
        对于(HashMapEntry项:adaptedHashMap.item)
            result.put(entry.key,entry.value);
        返回结果;
    }    公共静态类AdaptedHashMap {
        公开名单< HashMapEntry>项目=新的ArrayList< HashMapEntry>();
    }    公共静态类HashMapEntry {        @XmlAttribute
        公共字符串键;        @XmlValue
        公共字符串值;        公共HashMapEntry(){
        }        公共HashMapEntry(字符串键,字符串值){
            this.key =键;
            THIS.VALUE =价值;
        }
    }}

更多信息


更新


  

谢谢,这个作品。不过后来我得到了额外的
  注释在生产XML。有什么办法避免?


如果您使用的是 的EclipseLink MOXY 为您的< A HREF =htt​​p://jcp.org/en/jsr/detail?id=222相对=nofollow> JAXB(JSR-222) 供应商,那么你可以利用在 @XmlPath 扩展这个用例。我会用一个例子证明以下

在额外的 @XmlJavaTypeAdapter 我已经加入MOXY的 @在的HashMap 属性xmlpath中注释。的。的XML路径表示孩子应该被整理成家长XML元素。

 包forum13163430;进口的java.util.HashMap;
进口javax.xml.bind.annotation.XmlRootElement;
进口javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
进口org.eclipse.persistence.oxm.annotations.XmlPath;@XmlRootElement
公共类Foo {    私人的HashMap&LT;字符串,字符串&GT; HashMap的;    公共美孚(){
        this.hashMap =新的HashMap&LT;字符串,字符串&GT;();
    }    @XmlPath(。)
    @XmlJavaTypeAdapter(HashMapAdapter.class)
    公众的HashMap&LT;字符串,字符串&GT; getHashmap(){
        返回的HashMap;
    }    公共无效setHashmap(HashMap的&LT;字符串,字符串&GT;的HashMap){
        this.hashMap = HashMap的;
    }}

jaxb.properties

要指定MOXY为您的JAXB提供者,你需要包括一个名为 jaxb.properties 在同一封装与下面的条目(域模型文件参见:<一HREF =htt​​p://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html相对=nofollow> http://blog.bdoughan.com/2011/05/specifying -eclipselink-MOXY-AS-your.html )。

  javax.xml.bind.context.factory的= org.eclipse.persistence.jaxb.JAXBContextFactory

演示

由于MOXY是JAXB(JSR-222)兼容的实现,标准API可用于物体/转换为XML。

 包forum13163430;进口的java.io.File;
导入javax.xml.bind中*。公共类演示{    公共静态无效的主要(字串[] args)抛出异常{
        JAXBContext而JC = JAXBContext.newInstance(让Foo.class);        解组解组= jc.createUnmarshaller();
        文件中的XML =新的文件(SRC / forum13163430 / input.xml中);
        富富=(美孚)unmarshaller.unmarshal(XML);        编组编组= jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,真);
        的Marshaller.marshal(富下,System.out);
    }}

的input.xml /输出

下面是输入和输出从运行演示code。

&LT;?XML版本=1.0编码=UTF-8&GT?;
&LT;富&GT;
   &LT;项目关键=B&GT; B&LT; /项目&GT;
   &LT;项目关键=C&GT; C&LT; /项目&GT;
   &LT;项目关键=一个&gt;将&LT; /项目&GT;
&LT; / foo的&GT;

更多信息

I want to adapt the XML representation of a HashMap field using XmlAdapter. I use an ArrayList to do that. However, when marshalling the ArrayList is not marshalled at all. Why is that?

The code

@XmlRootElement
public class Foo {

    private HashMap<String, String> hashMap;

    public Foo() {
        this.hashMap = new HashMap<String, String>();
    }

    @XmlJavaTypeAdapter(HashMapAdapter.class)
    public HashMap<String, String> getHashmap() {
        return hashMap;
    }

    public void setHashmap(HashMap<String, String> hashMap) {
        this.hashMap = hashMap;
    }

}

public final class HashMapAdapter extends XmlAdapter<ArrayList<HashMapEntry>, HashMap<String, String>> {

    @Override
    public ArrayList<HashMapEntry> marshal(HashMap<String, String> arg0) throws Exception {
        ArrayList<HashMapEntry> result = new ArrayList<HashMapEntry>();
        for(Entry<String, String> entry : arg0.entrySet())
            result.add(new HashMapEntry(entry.getKey(), entry.getValue()));
        return result;
    }

    @Override
    public HashMap<String, String> unmarshal(ArrayList<HashMapEntry> arg0) throws Exception {
        HashMap<String, String> result = new HashMap<String, String>();
        for(HashMapEntry entry : arg0)
            result.put(entry.key, entry.value);
        return result;
    }

}

public class HashMapEntry {

    @XmlElement 
    public String key;

    @XmlValue
    public String value;

    public HashMapEntry() {

    }

    public HashMapEntry(String key, String value) {
        this.key = key;
        this.value = value;
    }
}

The result

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><hashmap/></foo>

解决方案

In your XmlAdapter you need to convert the HashMap to an an instance of an object with a List property instead of directly to an ArrayList.

HashMapAdapter

package forum13163430;

import java.util.*;
import java.util.Map.Entry;

import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public final class HashMapAdapter extends XmlAdapter<HashMapAdapter.AdaptedHashMap, HashMap<String, String>> {

    @Override
    public AdaptedHashMap marshal(HashMap<String, String> hashMap) throws Exception {
        AdaptedHashMap adaptedHashMap = new AdaptedHashMap();
        for(Entry<String, String> entry : hashMap.entrySet()) {
            adaptedHashMap.item.add(new HashMapEntry(entry.getKey(), entry.getValue()));
        }
        return adaptedHashMap;
    }

    @Override
    public HashMap<String, String> unmarshal(AdaptedHashMap adaptedHashMap) throws Exception {
        HashMap<String, String> result = new HashMap<String, String>();
        for(HashMapEntry entry : adaptedHashMap.item)
            result.put(entry.key, entry.value);
        return result;
    }

    public static class AdaptedHashMap {
        public List<HashMapEntry> item = new ArrayList<HashMapEntry>();
    }

    public static class HashMapEntry {

        @XmlAttribute 
        public String key;

        @XmlValue
        public String value;

        public HashMapEntry() {
        }

        public HashMapEntry(String key, String value) {
            this.key = key;
            this.value = value;
        }
    }

}

For More Information


UPDATE

Thanks, this works. However then I get an additional level of annotation in the produced XML. Is there any way to avoid that?

If you are using EclipseLink MOXy as your JAXB (JSR-222) provider then you can leverage the @XmlPath extension for this use case. I'll demonstrate below with an example.

Foo

On the hashmap property in additional to the @XmlJavaTypeAdapter I have added MOXy's @XmlPath annotation. An XML path of "." indicates that the child should be marshalled into the parents XML element.

package forum13163430;

import java.util.HashMap;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement
public class Foo {

    private HashMap<String, String> hashMap;

    public Foo() {
        this.hashMap = new HashMap<String, String>();
    }

    @XmlPath(".")
    @XmlJavaTypeAdapter(HashMapAdapter.class)
    public HashMap<String, String> getHashmap() {
        return hashMap;
    }

    public void setHashmap(HashMap<String, String> hashMap) {
        this.hashMap = hashMap;
    }

}

jaxb.properties

To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Demo

Since MOXy is JAXB (JSR-222) compliant implementation, the standard APIs can be used to convert objects from/to XML.

package forum13163430;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum13163430/input.xml");
        Foo foo = (Foo) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(foo, System.out);
    }

}

input.xml/Output

Below is the input to and output from running the demo code.

<?xml version="1.0" encoding="UTF-8"?>
<foo>
   <item key="b">B</item>
   <item key="c">C</item>
   <item key="a">A</item>
</foo>

For More Information

这篇关于JAXB编组由XmlAdapter创建一个ArrayList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆