【问题标题】:resteasy @Consume json fails with java.util.Mapresteasy @Consume json 因 java.util.Map 而失败
【发布时间】:2015-10-06 14:40:46
【问题描述】:

我有以下 json 结构:

{
    "foo" : {
        "foo1" : {
            "txt" : "val",
            "txt1" : "val1",
            "txt2" : "val2",
        },
        "foo2" : {
            "txt" : "val",
            "txt1" : "val1",
            "txt2" : "val2",
        }
    },
    "bar" : {
        "bar1": {
            "txt" : "val",
            "txt1" : "val1",
            "txt2" : "val2",
        },
        "bar2": {
            "txt" : "val",
            "txt1" : "val1",
            "txt2" : "val2",
        }
    }
}

虽然我有以下pojo:

class Pojo {
  String txt;
  String txt1;
  String txt2;
}

我的resteasy方法看起来像:

@POST
@Produces({ MediaType.APPLICATION_JSON })
@Consumes({ MediaType.APPLICATION_JSON })
@Path("/foo")
public void bar(@QueryParam("jsonObj") Map<String,Map<String,Pojo>> jsonObj);

但是在启动服务器时出现以下错误:

java.lang.RuntimeException: 找不到接受 字符串参数或 valueOf() 或 fromString() 方法 公共抽象 void 上的 javax.ws.rs.QueryParam("jsonObj") com.foo.FooBar.bar(java.util.Map) for basetype: java.util.Map at org.jboss.resteasy.core.StringParameterInjector.initialize(StringParameterInjector.java:217) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.StringParameterInjector.(StringParameterInjector.java:61) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.QueryParamInjector.(QueryParamInjector.java:28) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.InjectorFactoryImpl.createParameterExtractor(InjectorFactoryImpl.java:85) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.MethodInjectorImpl.(MethodInjectorImpl.java:42) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.InjectorFactoryImpl.createMethodInjector(InjectorFactoryImpl.java:76) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.ResourceMethodInvoker.(ResourceMethodInvoker.java:100) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.ResourceMethodRegistry.processMethod(ResourceMethodRegistry.java:280) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.ResourceMethodRegistry.register(ResourceMethodRegistry.java:251) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:221) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:193) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.core.ResourceMethodRegistry.addResourceFactory(ResourceMethodRegistry.java:179) ~[resteasy-jaxrs-3.0.9.Final.jar:na] 在 org.jboss.resteasy.plugins.spring.SpringBeanProcessor.onApplicationEvent(SpringBeanProcessor.java:486) ~[resteasy-spring-3.0.9.Final.jar:na] 在 org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:96) ~[spring-context-3.2.8.RELEASE.jar:3.2.8.RELEASE] 在 org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:334) ~[spring-context-3.2.8.RELEASE.jar:3.2.8.RELEASE] 在 org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:948) ~[spring-context-3.2.8.RELEASE.jar:3.2.8.RELEASE] 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) ~[spring-context-3.2.8.RELEASE.jar:3.2.8.RELEASE] 在 org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:410) ~[spring-web-3.2.8.RELEASE.jar:3.2.8.RELEASE] 在 org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) ~[spring-web-3.2.8.RELEASE.jar:3.2.8.RELEASE] 在 org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) [spring-web-3.2.8.RELEASE.jar:3.2.8.RELEASE] 在 org.jboss.resteasy.plugins.spring.SpringContextLoaderListener.contextInitialized(SpringContextLoaderListener.java:48) [resteasy-spring-3.0.9.Final.jar:na] 在 org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939) [catalina.jar:7.0.47] 在 org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434) [catalina.jar:7.0.47] 在 org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:7.0.47] 在 org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [catalina.jar:7.0.47] 在 org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [catalina.jar:7.0.47] 在 java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0-45] 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0-45] 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0-45] 在 java.lang.Thread.run(Thread.java:744) [na:1.7.0-45]

我查看了documentation,对于复杂对象,它说要使用 StringConvertor,但它不应该支持简单类型,如 List、Map 等...

【问题讨论】:

  • 正如错误消息(和documentation)所述,您不能自动将参数注入映射,因为它是一个接口,因此没有只有一个参数的构造函数,也没有@987654327 @ 或 fromString() 方法。但是,您可以尝试定义一个自定义的javax.ws.rs.ext.ParamConverter implementation,它会为您创建一个地图。
  • 另外,你真的提供这个 JSON 结构作为查询参数吗?
  • 所以在 fromString 中的自定义转换器中,我必须解析 json 并转换为 Map 分配回 Map?如果是这种情况,那么我最好只接受参数作为字符串并将其转换为自己
  • “此外,您真的提供此 JSON 结构作为查询参数吗?”好点子。因为它是一个帖子,我认为我最好使用@FormParam
  • 在这种情况下,任何参数注释都不合适,因为您显然在 POST 请求中将 JSON 作为正文发送。您可以控制 JSON 格式吗?如果是这样,请将其更改为包含 foo(或 bar)的列表,其中还包含 foo1(或 bar1)的列表,这些列表实际上包含您的 pojo,并更新您的 pojo 以适应修改后的设计。如果没有,只需使用 InputStream 或 String 方法参数(不带任何注释)并自行创建对象(或使用 MessageBodyReader 将输入流转换为您的 pojo)。

标签: java resteasy


【解决方案1】:

您可以使用 InputStream 而不是采用 Map> jsonObj 格式的 JSON,然后您可以处理输入流以从中获取对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    • 2012-10-03
    • 2014-07-16
    相关资源
    最近更新 更多