JAXB无法编组类型“java.util.HashMap”

时间:2015-01-05 13:53:58

标签: java interface jaxb hashmap

我有一个地图,其中字符串作为键,接口作为值。我编写了一个处理接口的适配器,并为map字段提供了注释@XmlAnyElement。现在我收到错误说"无法编组类型" java.util.HashMap"作为元素,因为它缺少@XmlRootElement注释"。在这件事上有人可以帮助我吗?

1 个答案:

答案 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