JAXB编组由XmlAdapter创建一个ArrayList [英] JAXB marshal an ArrayList created by XmlAdapter
问题描述
我想用 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 =http://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 =http://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 usingXmlAdapter
. I use anArrayList
to do that. However, when marshalling theArrayList
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 theHashMap
to an an instance of an object with aList
property instead of directly to anArrayList
.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屋!