以前有几个关于使用JaxB来编组/解组java.util.Map
的问题,其中许多问题都指向了这个例子,这很好用:
http://blog.bdoughan.com/2013/03/jaxb-and-javautilmap.html
但是,如果地图不是@XmlRootElement
的成员,我无法让JaxB能够编组/解组地图实例。例如,这是一个根元素类,
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public static class Customer {
private MyField myField
MyField getMyField() {
return myField
}
void setMyField(MyField myField) {
this.myField = myField
}
}
它的字段类的定义:
@XmlAccessorType(XmlAccessType.FIELD)
public static class MyField{
Map<String, String> getSomeMap() {
return someMap
}
void setSomeMap(Map<String, String> someMap) {
this.someMap = someMap
}
@XmlElement
private Map<String, String> someMap = new HashMap<String, String>()
}
还有一些驱动编组的代码:
JAXBContext jc = JAXBContext.newInstance(Customer.class)
Customer customer = new Customer()
MyField myField1 = new MyField()
myField1.someMap.put("foo", "bar")
myField1.someMap.put("baz", "qux")
customer.myField = myField1
Marshaller marshaller = jc.createMarshaller()
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true)
marshaller.marshal(customer, System.out)
此示例导致:
java.util.Map is an interface, and JAXB can't handle interfaces.
java.util.Map does not have a no-arg default constructor.
我在Groovy而不是Java中编写代码,但我认为它不会产生太大的影响。
答案 0 :(得分:1)
通过使用Spring Boot创建一个@RestController类型的TestController,我能够使用JAXB遇到相同的行为。
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping(value = "test")
class TestController {
@RequestMapping(value = "findList")
List findList() {
["Test1", "Test2", "Test3"] as ArrayList<String>
}
@RequestMapping(value = "findMap")
Map findMap() {
["T1":"Test1", "T2":"Test2", "T3":"Test3"] as HashMap<String,String>
}
@RequestMapping(value = "")
String find(){
"Test Something"
}
}
使用JAXB作为SpringBoot中的默认实现,我可以重现/ test / findList将正确呈现XML的问题,但/ test / findMap会产生错误,如初始发布中所述。
对我来说,问题的解决方案是将XML渲染库切换到Jackson(还有其他像XStream)。
使用Gradle作为构建文件(build.gradle),我只需添加Jackson依赖项,非常类似于使用Maven时的情况:
&#39; com.fasterxml.jackson.core:杰克逊 - 芯:2.7.1&#39 ;, &#39; com.fasterxml.jackson.core:杰克逊 - 注解:2.7.1&#39 ;, &#39; com.fasterxml.jackson.core:杰克逊 - 数据绑定:2.7.1-1&#39 ;, &#39; com.fasterxml.jackson.dataformat:杰克逊 - DATAFORMAT-XML:2.7.1&#39 ;, &#39; org.codehaus.woodstox:woodstox芯-ASL:4.4.1&#39;,
答案 1 :(得分:0)
我在自己面前经历过这个。底线是警告告诉你确切的问题。您已将字段定义为java.util.Map类型。 JAXB不支持接口。要纠正您的问题,您需要将字段的声明更改为具体的Map类型,如:
private HashMap<String, String> someMap = new HashMap<String, String>()
您引用的链接中描述了您的其他选项。你需要一个
MapAdapter 类在您提供的链接中引用,然后将其包含在注释中,向JAXB提示如何编组/解组Map类型。
我认为这个链接提供了一个更清晰的示例,说明如何创建和实现MapAdapter:
答案 2 :(得分:0)
我遇到的具体问题的答案最终是从@XmlElement
字段中移除Map
注释,如下所示:
@XmlAccessorType(XmlAccessType.FIELD)
public static class MyField{
Map<String, String> getSomeMap() {
return someMap
}
void setSomeMap(Map<String, String> someMap) {
this.someMap = someMap
}
//@XmlElement Remove this annotation
private Map<String, String> someMap = new HashMap<String, String>()
}
如果没有该注释,编组/解组工作正常,并仍然将Map
解释为XmlElement - 具体来说,该注释似乎存在错误。但是,正如@dlcole指出的那样,另一种选择(允许您对序列化表示的格式有更多控制权)是使用Jackson而不是JAXB。