我有一个地图,其中字符串作为键,接口作为值。我编写了一个处理接口的适配器,并为map字段提供了注释@XmlAnyElement。现在我收到错误说"无法编组类型" java.util.HashMap"作为元素,因为它缺少@XmlRootElement注释"。在这件事上有人可以帮助我吗?
答案 0 :(得分:0)
此错误是由于Map没有XmlRootElement。让我们看一个例子:
这是界面:
public interface IEmployee {
String getFirstName();
void setFirstName(final String firstName);
String getLastName();
void setLastName(final String lastName);
}
这就是具体实施:
@XmlRootElement(name = "employee")
public class Employee implements IEmployee {
private String firstName;
private String lastName;
// getters and setters
}
带地图的JAXB对象:
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "employees")
@XmlAccessorType(XmlAccessType.FIELD)
public class EmployeeMap {
@XmlJavaTypeAdapter(EmployeeMapAdapter.class)
private Map<String, IEmployee> map;
// getter and setter
}
我们需要创建一个适配器来处理EmployeeMap
中的地图,其中包含一个模拟地图的列表。看起来像这样:
public class EmployeeMapAdapter extends XmlAdapter<EmployeeMapAdapter.AdaptedMap, Map<String, Employee>> {
public static class AdaptedMap {
public List<Entry> entry = new ArrayList<>();
public static class Entry {
public String key;
public Employee value;
}
}
@Override
public AdaptedMap marshal(final Map<String, Employee> map) throws Exception {
final AdaptedMap adaptedMap = new AdaptedMap();
for (final Map.Entry<String, Employee> mapEntry : map.entrySet()) {
final Entry entry = new Entry();
entry.key = mapEntry.getKey();
entry.value = mapEntry.getValue();
adaptedMap.entry.add(entry);
}
return adaptedMap;
}
@Override
public Map<String, Employee> unmarshal(final AdaptedMap adaptedMap) throws Exception {
final Map<String, Employee> map = new HashMap<>();
for (final Entry entry : adaptedMap.entry) {
map.put(entry.key, entry.value);
}
return map;
}
}
由于JAXB不处理接口,只处理值类和内容接口,因此适配器必须使用具体的实现。
编组示例:
final Map<String, IEmployee> map = new HashMap<>();
final Employee emp1 = new Employee();
emp1.setFirstName("Bruno");
emp1.setLastName("César");
map.put("1", emp1);
final Employee emp2 = new Employee();
emp2.setFirstName("Ribeiro");
emp2.setLastName("Silva");
map.put("2", emp2);
final EmployeeMap employeeMap = new EmployeeMap();
employeeMap.setMap(map);
final JAXBContext jaxbContext = JAXBContext.newInstance(EmployeeMap.class);
final Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
final File file = new File("D:/Temp/employees.xml");
if (!file.exists()) {
file.mkdirs();
}
jaxbMarshaller.marshal(employeeMap, file);
结果:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employees>
<map>
<entry>
<key>2</key>
<value>
<firstName>Ribeiro</firstName>
<lastName>Silva</lastName>
</value>
</entry>
<entry>
<key>1</key>
<value>
<firstName>Bruno</firstName>
<lastName>César</lastName>
</value>
</entry>
</map>
</employees>
解组:
final JAXBContext jaxbContext = JAXBContext.newInstance(EmployeeMap.class);
final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
final EmployeeMap empMap = (EmployeeMap) jaxbUnmarshaller.unmarshal(new File("D:/temp/employees.xml"));
for (final String id : empMap.getMap().keySet()) {
System.out.println(empMap.getMap().get(id).getFirstName());
System.out.println(empMap.getMap().get(id).getLastName());
}
结果:
Ribeiro
Silva
Bruno
César