需要一种从 JAX RS 服务中的 List<Map<String,String> 生成 JSON 的方法。杰克逊2
Need a way to generate JSON from List<Map<String,String> in JAX RS service. jackson2
我的 POM.xml 中有以下内容
已更新完整 pom:
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.19</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.19</version>
</dependency>
<!-- <dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.19</version>
</dependency> -->
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
<version>2.2.1.Final</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.drill.exec</groupId>
<artifactId>drill-jdbc-all</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
我想从 List<Map<String,String>>
生成一个 JSON。我总是以 MessageBodyWriter not found for media type=application/json, type=class java.util.LinkedHashMap, genericType=jav a.util.Map<String,String>
我什至尝试过简单的地图
@GET
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public Map<String, String> getMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("some key", "some value");
return map;
}
即使这样也会产生相同的错误消息。
更新异常堆栈跟踪:
Jul 29, 2015 9:23:29 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [CustomerDataService] in context with path [/CustomerDataService] threw exception
[org.glassfish.jersey.server.ContainerException: java.lang.AbstractMethodError: com.fasterxml.jackson.jaxrs.json.Jackson
JaxbJsonProvider.isWriteable(Ljava/lang/Class;Ljava/lang/reflect/Type;[Ljava/lang/annotation/Annotation;Ljavax/ws/rs/cor
e/MediaType;)Z] with root cause
java.lang.AbstractMethodError: com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider.isWriteable(Ljava/lang/Class;Lja
va/lang/reflect/Type;[Ljava/lang/annotation/Annotation;Ljavax/ws/rs/core/MediaType;)Z
at org.glassfish.jersey.message.internal.MessageBodyFactory.isWriteable(MessageBodyFactory.java:1158)
at org.glassfish.jersey.message.WriterModel.isWriteable(WriterModel.java:86)
at org.glassfish.jersey.message.internal.MessageBodyFactory._getMessageBodyWriter(MessageBodyFactory.java:798)
at org.glassfish.jersey.message.internal.MessageBodyFactory.getMessageBodyWriter(MessageBodyFactory.java:756)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterc
eptorExecutor.java:241)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:106)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInter
ceptor.java:86)
您不能序列化集合和地图。创建容器 class.
例如:
@XmlRootElement
public class Container {
public Map<String, String> data;
}
public Container getMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("some key", "some value");
// wrap content int container object
Container container = new Container();
container.data = map;
return container ;
}
这个问题的原因是,XML 总是必须有一个根元素。
MOXy 不能很好地处理地图,因为它在引擎盖下使用 JAXB,而 JAXB 很糟糕。改用杰克逊。摆脱对 MOXy 的依赖。 MOXy 是默认的,所以如果它在类路径上,它将优先于所有其他的使用。一拿出来就用Jackson
更新
所以 drill-jdbc-all
实际上重新打包了 Jackson 1.x 和 Jackson 2.x。您可以将它们从 jersey-media-json-jackson
依赖项中排除,因为 drill 已经包含它们。
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.19</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
更新 2
我猜以上还是不行。我 是 能够开始工作的一种方法是添加 jackson-jaxrs-json-provider
(您还需要取出 jersey-media-json-jackson 和 jersey-media- moxy).
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.drill.exec</groupId>
<artifactId>drill-jdbc-all</artifactId>
<version>1.1.0</version>
</dependency>
关键是它必须在apache-jdbc-drill
之前声明。是的,它似乎更像是一个解决方案。但是 drill 打包依赖的事实是一个问题。当 Jersey 扫描时,它会先添加我们的,而忽略 drill 的。
然后您需要将提供程序添加到您的 Jersey 配置中
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider
</param-value>
</init-param>
我的意思是我没有测试过这 10,000 个,但是对于我测试的 10 到 20 次,依赖项的顺序是它是否有效的决定因素。同样,就像我说的,这似乎是一种解决方法。
并将其添加到 Jersey 配置中
我的 POM.xml 中有以下内容 已更新完整 pom:
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.19</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.19</version>
</dependency>
<!-- <dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.19</version>
</dependency> -->
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
<version>2.2.1.Final</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.drill.exec</groupId>
<artifactId>drill-jdbc-all</artifactId>
<version>1.1.0</version>
</dependency>
</dependencies>
我想从 List<Map<String,String>>
生成一个 JSON。我总是以 MessageBodyWriter not found for media type=application/json, type=class java.util.LinkedHashMap, genericType=jav a.util.Map<String,String>
我什至尝试过简单的地图
@GET
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public Map<String, String> getMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("some key", "some value");
return map;
}
即使这样也会产生相同的错误消息。
更新异常堆栈跟踪:
Jul 29, 2015 9:23:29 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [CustomerDataService] in context with path [/CustomerDataService] threw exception
[org.glassfish.jersey.server.ContainerException: java.lang.AbstractMethodError: com.fasterxml.jackson.jaxrs.json.Jackson
JaxbJsonProvider.isWriteable(Ljava/lang/Class;Ljava/lang/reflect/Type;[Ljava/lang/annotation/Annotation;Ljavax/ws/rs/cor
e/MediaType;)Z] with root cause
java.lang.AbstractMethodError: com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider.isWriteable(Ljava/lang/Class;Lja
va/lang/reflect/Type;[Ljava/lang/annotation/Annotation;Ljavax/ws/rs/core/MediaType;)Z
at org.glassfish.jersey.message.internal.MessageBodyFactory.isWriteable(MessageBodyFactory.java:1158)
at org.glassfish.jersey.message.WriterModel.isWriteable(WriterModel.java:86)
at org.glassfish.jersey.message.internal.MessageBodyFactory._getMessageBodyWriter(MessageBodyFactory.java:798)
at org.glassfish.jersey.message.internal.MessageBodyFactory.getMessageBodyWriter(MessageBodyFactory.java:756)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterc
eptorExecutor.java:241)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:106)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInter
ceptor.java:86)
您不能序列化集合和地图。创建容器 class.
例如:
@XmlRootElement
public class Container {
public Map<String, String> data;
}
public Container getMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("some key", "some value");
// wrap content int container object
Container container = new Container();
container.data = map;
return container ;
}
这个问题的原因是,XML 总是必须有一个根元素。
MOXy 不能很好地处理地图,因为它在引擎盖下使用 JAXB,而 JAXB 很糟糕。改用杰克逊。摆脱对 MOXy 的依赖。 MOXy 是默认的,所以如果它在类路径上,它将优先于所有其他的使用。一拿出来就用Jackson
更新
所以 drill-jdbc-all
实际上重新打包了 Jackson 1.x 和 Jackson 2.x。您可以将它们从 jersey-media-json-jackson
依赖项中排除,因为 drill 已经包含它们。
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.19</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-base</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
更新 2
我猜以上还是不行。我 是 能够开始工作的一种方法是添加 jackson-jaxrs-json-provider
(您还需要取出 jersey-media-json-jackson 和 jersey-media- moxy).
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.drill.exec</groupId>
<artifactId>drill-jdbc-all</artifactId>
<version>1.1.0</version>
</dependency>
关键是它必须在apache-jdbc-drill
之前声明。是的,它似乎更像是一个解决方案。但是 drill 打包依赖的事实是一个问题。当 Jersey 扫描时,它会先添加我们的,而忽略 drill 的。
然后您需要将提供程序添加到您的 Jersey 配置中
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider
</param-value>
</init-param>
我的意思是我没有测试过这 10,000 个,但是对于我测试的 10 到 20 次,依赖项的顺序是它是否有效的决定因素。同样,就像我说的,这似乎是一种解决方法。
并将其添加到 Jersey 配置中