java - JAXB 无法编码(marshal)类型 "java.util.HashMap"

标签 java interface jaxb hashmap

我有一个以字符串作为键、以接口(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/

相关文章:

java - 谁控制output.log和error.log文件?

带有接口(interface)的 C# 重载方法行为

Grails 3.3.3 generate-all <domain class> 只创建服务接口(interface)

java - 解码映射到属性的元素时未找到描述符

java - JAXB Ant Task - 从哪里获得 JAR?

java - 如何知道用户是否退出 Facebook,FB.Event.Subscribe 不起作用

java - EL表达式可以访问作用域中的子对象的子对象吗?

java - 当尝试运行我的java程序时,我收到错误: java. lang.ClassNotFoundException : jdk. tools.jaotc.Main

asp.net-mvc-3 - 使用接口(interface)作为局部 View 的模型类型+数据注释

java - JAXB:如何获取包装类型的值(value)?