JAXB将XML元素解组为HashMap

我发现很多文章描述了如何将一系列XML元素解组到HashMap,只要它们在“父”元素中。 但是,我没有让这个与直接在根元素下的孩子一起工作!

选项1 – 工程:

     ...   

选项2 – 不起作用:

     ...  

检查:

 package com.foo.conf; import java.util.Map; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement(name="checks") public class Checks { @XmlJavaTypeAdapter(ChecksAdapter.class) @XmlElement(name="checks") public Map checkMap; } 

检查:

 package com.foo.conf; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlValue; public class Check { @XmlAttribute public String key; @XmlValue public String description; public Check() { } public Check(String key) { this.key = key; } public String getCheckKey() { return this.key; } } 

CheckMapType:

 package com.foo.conf; import java.util.List; import javax.xml.bind.annotation.XmlElement; class CheckMapType { @XmlElement(name="check") public List checkList; // = new ArrayList(); } 

ChecksAdapter:

 package com.foo.conf; import java.util.HashMap; import java.util.Map; import javax.xml.bind.annotation.adapters.XmlAdapter; final class ChecksAdapter extends XmlAdapter<CheckMapType, Map> { @Override public CheckMapType marshal(Map arg0) throws Exception { return null; } @Override public Map unmarshal(CheckMapType arg0) throws Exception { System.out.println("u: " + arg0.checkList.size()); Map map = new HashMap(); for (Check check : arg0.checkList) { System.out.println(check); map.put(check.key, check); } return map; } } 

这是(一些虚拟测试行)我如何生成类/调用解组:

 JAXBContext jc = JAXBContext.newInstance(Checks.class); Unmarshaller u = jc.createUnmarshaller(); Checks c = (Checks) u.unmarshal(new File("checks.xml")); System.out.println(c.checkMap.size()); 

关于如何让选项#2工作的任何想法? 它在使用List而不是Map时起作用,但我需要HashMap,因为我必须通过给定的键访问对象…

任何提示非常感谢!

注意:我是EclipseLink JAXB(MOXy)的负责人,也是JAXB(JSR-222)专家组的成员。

JAXB将使用嵌套关系处理每个对象关系。 Map被视为Object而不是Collection因此这就是您获得所见行为的原因。

MOXy有一个名为@XmlPath基于XPath的映射扩展,可用于此用例。

 package com.foo.conf; import java.util.Map; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.eclipse.persistence.oxm.annotations.XmlPath; @XmlRootElement(name="checks") public class Checks { @XmlJavaTypeAdapter(ChecksAdapter.class) @XmlPath(".") public Map checkMap; } 

了解更多信息

你是如何生成JAXB类的? 我不确定你到底想要做什么,但下面非常简单的代码对我有用..

  JAXBContext jc = JAXBContext.newInstance(ChecksType.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); ChecksType chksType = (ChecksType) unmarshaller.unmarshal(new File("/path/to/xml")); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(chksType, System.out); System.err.println(chksType.getCheck().get(0).getKey()); for (CheckType checkType : chksType.getCheck()) { System.out.println("key = " + checkType.getKey() + ", " + checkType); } 

这是我的JAXB生成的类.. ChecksType (根元素)

  @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "checksType", propOrder = { "check" }) @XmlRootElement(name = "checks") public class ChecksType { @XmlElement(required = true) protected List check; public List getCheck() { if (check == null) { check = new ArrayList(); } return this.check; } } 

checkType (孩子)

  @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "checkType") public class CheckType { @XmlAttribute(name = "key") protected String key; public String getKey() { return key; } public void setKey(String value) { this.key = value; } }