【问题标题】:Moxy can't marshal List<String> into JSONMoxy 无法将 List<String> 编组为 JSON
【发布时间】:2015-03-29 04:16:25
【问题描述】:

我有一个使用 Jersey 2.6 框架运行 servlet 的 Tomcat 服务器。在 servlet 中,我将 Jackson 用于 JSON POJO 编组。我最近了解了 Moxy,并正在尝试改用它,因为它似乎是 Jersey 的首选。

目前,我的 POM 中有以下内容:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.6</version>
</dependency>

我的 RESTful 服务之一如下:

 @GET
 @Path("threatSeverities")
 @Produces(MediaType.APPLICATION_JSON)
 public List<String> getThreatSeverities() {
     return dc.selectAllSeverities();
 }

这对杰克逊很有效。当我更改为 Moxy 时,单元测试如下:

 @Test
 public void testThreatSeverities() {
     final Response response = target("threatSeverities").request().get();
     List<String> severities = response.readEntity(new GenericType<List<String>> () {});
     assertNotNull(severities);
 }

会产生以下错误:

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=text/plain, type=interface java.util.List, genericType=java.util.List<java.lang.String>.
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:225)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:149)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1124)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:853)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:812)
at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:377)
at org.glassfish.jersey.client.InboundJaxrsResponse$2.call(InboundJaxrsResponse.java:122)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:398)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:119)
at com.hp.it.scv.mobile.rest.RestTest.testThreatSeverities(RestTest.java:85)
at (... truncated)

有趣的事情要注意,即使控制器方法 getThreatSeverities 有一个 @Produces(MediaType.APPLICATION_JSON),似乎 Moxy(或其他我不知道的东西)正在将响应的 Content-Type 标头更改为 @ 987654328@ 在单元测试中。这一切都没有发生在杰克逊身上。

还有一点需要注意,这似乎是 List&lt;String&gt; 对象所特有的。 Moxy 可以毫无问题地编组 POJO 列表。

  1. Moxy 本身是否支持将 List&lt;String&gt; 对象编组为 JSON 字符串?似乎答案是否定的。我在网上找不到确切的答案。我想知道是否需要为List&lt;String&gt; 对象编写自己的MessageBodyReaderMessageBodyWriter
  2. 有人知道在使用 Moxy 时可以将 Content-Type 标头更改为 text/plain 吗?我怀疑是 Moxy,可能是因为它发现我正在尝试返回一个简单的字符串列表。

更新(2015 年 2 月 2 日):

正如 peeskillet 所指出的,返回的响应是 HTTP 500。我能够从响应中提取堆栈跟踪并得到以下信息:

Stack trace: javax.ws.rs.WebApplicationException: HTTP 500 Internal Server Error
at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.java:810)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:263)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:250)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:103)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:88)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1154)
at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:571)
at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:378)
at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:368)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:262)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:319)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1028)
at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:363)
at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:217)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Unknown Source)
Caused by: javax.xml.bind.MarshalException - with linked exception:
[Exception [EclipseLink-25003] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred marshalling the object
Internal Exception: Exception [EclipseLink-25007] (Eclipse Persistence  Services - 2.5.0.v20130507-3faac2b):  org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class java.lang.String was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.]
at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:403)
at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.java:808)
... 25 more
Caused by: Exception [EclipseLink-25003] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: An error occurred marshalling the object
Internal Exception: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class java.lang.String was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
at org.eclipse.persistence.exceptions.XMLMarshalException.marshalException(XMLMarshalException.java:97)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:911)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:848)
at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:401)
... 26 more
Caused by: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor for class java.lang.String was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
at org.eclipse.persistence.exceptions.XMLMarshalException.descriptorNotFoundInProject(XMLMarshalException.java:139)
at org.eclipse.persistence.internal.oxm.Context$ContextState.getSession(Context.java:143)
at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:787)
at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:1)
at org.eclipse.persistence.internal.oxm.Context.getSession(Context.java:451)
at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:356)
at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:1)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:568)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:1096)
at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:869)
... 28 more

Exception Description: A descriptor for class java.lang.String was not found in the project. 看来,如果不手动编码,就无法实现从List&lt;String&gt; 到 JSON 编组。

【问题讨论】:

  • 异常看起来在客户端。我没有机会测试它,所以我不确定你的第一个问题,但对于第二个问题,看起来你正在使用 JerseyTest 框架。如果您使用的是 grizzley 容器。如果有 500,它将被映射到一个灰熊响应,即text/plain。您可以从响应中获取状态码以查看是否为 500
  • 好点。我刚刚添加了System.out.println(response.getHeaderString("Content-type")); System.out.println(response.getStatus()); 并返回了text-plain 500。这就回答了第二个问题。我仍然想知道为什么 Moxy 不能简单地将 List&lt;String&gt; 转换为 JSON。
  • moxy 可以做到,我有一些类似的奇怪错误,原因似乎并不相关。请尝试在您的测试中包含 .request(MediaType.APPLICATION_JSON_TYPE)

标签: java json jersey moxy


【解决方案1】:

MOXy 代码 (moxy/org.eclipse.persistence.moxy/src/org/eclipse/persistence/jaxb/rs/MOXyJsonProvider.java) 中有一些不明确的限制,阻止它处理“java.*”的集合类。我已经对此提出了问题。

https://bugs.eclipse.org/bugs/show_bug.cgi?id=459227

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    • 1970-01-01
    • 2013-08-27
    相关资源
    最近更新 更多