我有一个以字符串作为键、以接口(interface)作为值的映射。我编写了一个适配器来处理接口(interface),并向 map 字段提供了注释 @XmlAnyElement。现在我收到错误消息“无法将类型“java.util.HashMap”编码(marshal)为元素,因为它缺少 @XmlRootElement 注释”。有人可以帮我解决这个问题吗?
最佳答案
此错误是由于 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
}
带 map 的 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
中的 map ,并使用模拟 map 的列表。看起来像这样:
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 不处理接口(interface),只处理值类和内容接口(interface),因此适配器必须使用具体实现。
编码示例:
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
关于java - JAXB 无法编码(marshal)类型 "java.util.HashMap",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27780999/