java - 如何使用 JAXB 编码 Map<String, List<Objects>>

标签 java jaxb

我的代码遇到了问题。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@Entity
@NamedQueries({
    @NamedQuery(name = Parameter.FIND_ALL, query = "SELECT pm FROM Parameter pm")
})
public class Parameter implements Serializable {

    public static final String FIND_ALL = "Parameter.findAll";

    @XmlTransient
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue
    private Long id;
    @XmlAttribute
    private String type;

    private String name;

    // Setters and Getters
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class ParameterMap {
    private Map<String, List<Parameter>> parameterMap = new HashMap<String, List<Parameter>>();

    @XmlElement
    public Map<String, List<Parameter>> getParameterMap() {
        return parameterMap;
    }

    public void setParmeterMap(Map<String, List<Parameter>> parameterMap) {
        this.parameterMap = parameterMap;
    }
}

@Path("/parameter")
public class ParameterRESTResource {

    @Inject
    private ParameterService paramService;

    @GET
    @Path("/")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public List<Parameter> getAllParameters() throws JAXBException {

        ParameterMap parameterMap = formatParameters(paramService.getAllParameters());

        JAXBContext jaxbContext = JAXBContext.newInstance(ParameterMap.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        jaxbMarshaller.marshal(parameterMap, System.out);
        jaxbMarshaller.marshal(parameterMap, new File("c:/temp/employees.xml"));

        return paramService.getAllParameters();
    }

    public ParameterMap formatParameters(List<Parameter> parameters) {
        HashMap<String, List<Parameter>> parameterMap = new HashMap<String, List<Parameter>>();
        ParameterMap paramMap = new ParameterMap();
        Parameter param = null;

        List<Parameter> list = null;

        for (int i = 0; i < parameters.size(); i++) {
            param = new Parameter();

            param = parameters.get(i);

            if (param.getType() != "text") {
                list = new ArrayList<Parameter>();

                if (parameterMap.containsKey(param.getName())) {
                    list = parameterMap.get(param.getName());
                    list.add(param);
                }
                else {
                    list = new ArrayList<Parameter>();
                    list.add(param);
                }

            }
            else {
                list = new ArrayList<Parameter>();
                list.add(param);

            }

            parameterMap.put(param.getName(), list);

        }

        paramMap.setParmeterMap(parameterMap);
        return paramMap;
    }
}

当我在本地 ( http://localhost:8080/home/rest/parameter/ ) 上运行应用程序时,出现以下错误。我的主要要求是显示 Map<String,List<Parameters>>在带有包含所有信息的 xml 的 UI 上。

org.jboss.resteasy.spi.UnhandledException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions java.util.List is an interface, and JAXB can't handle interfaces. this problem is related to the following location: at java.util.List at private java.util.Map nl.paston.insurance.product.model.ParameterMap.parameterMap at nl.paston.insurance.product.model.ParameterMap org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76) org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:212) org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:149) org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:372) org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179) org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220) org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) javax.servlet.http.HttpServlet.service(HttpServlet.java:790) io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:86) io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78) io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131) io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72) io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50) io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61) io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:282) io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:261) io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:80) io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:172) io.undertow.server.Connectors.executeRootHandler(Connectors.java:199) io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:774) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) java.lang.Thread.run(Thread.java:745)

我希望我已经提供了所有需要的信息。在这个专家组里,请大家帮我解决这个问题。任何小小的帮助都会对我有很大的帮助。提前感谢您的帮助。

最佳答案

包含集合作为值的 map 有点棘手;您需要一个适配器和类来以 JAXB 可以处理的方式表示映射条目。

@XmlAccessorType(XmlAccessType.FIELD) 
public class ListOfEntry {
    @XmlElement
    private List<Entry> list = new ArrayList<>();
    public List<Entry> getList(){ return list; }
}

@XmlAccessorType(XmlAccessType.FIELD) 
public class Entry {
    @XmlElement
    private String key;
    @XmlElement
    private List<Parameter> list = new ArrayList<>();
    public String getKey(){ return key; }
    public void setKey( String value ){ key = value; }
    public List<Parameter> getList(){ return list; }
}

适配器来回进行转换:

public class Adapter 
extends XmlAdapter<ListOfEntry, Map<String, List<Parameter>>> {
    @Override
    public Map<String, List<Parameter>> unmarshal(ListOfEntry loe)
        throws Exception {
        Map<String, List<Parameter>> map = new HashMap<>();
        for(Entry entry : loe.getList() ) {
            map.put(entry.getKey(), entry.getList() );
        }
        return map;
    }

    @Override
    public ListOfEntry marshal(Map<String, List<Parameter>> map)
        throws Exception {
        ListOfEntry loe = new ListOfEntry();
        for(Map.Entry<String, List<Parameter>> mapEntry : map.entrySet()) {
            Entry entry = new Entry();
            entry.setKey( mapEntry.getKey() );
            entry.getList().addAll( mapEntry.getValue() );
            loe.getList().add(entry);
        }
        return loe;
    }
}

并且你必须在 map 字段中添加注释:

@XmlElement
@XmlJavaTypeAdapter(Adapter.class)
private Map<String, List<Parameter>> parameterMap = new HashMap<>();

关于java - 如何使用 JAXB 编码 Map<String, List<Objects>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33190939/

相关文章:

java - 将 URL 中的图像加载到 gridview 中

jaxb - Umarshall JSON 对象,在 Jackson 和 JAXB 之间带有下划线和驼峰式字段

java - JAXb 在解码期间不填充对象

java - 您可以选择通过 JAXB 序列化类属性吗?

java - 使用包含 CDATA 的 XML 配置 MOXy 的 @XmlPath

xml - JAXB 如何删除 JDK7 中的 ns2

java - 在 Java 中通过循环创建乘法表

c# - 从 Java 到 C# 的函数

java - 如何在java中重现竞争条件?

java - 如何管理文件中的空行