获取“MessageBodyWriter not found for media type=application/json”试图通过 JAX-RS Web 服务发送 JSON 对象

Posted

技术标签:

【中文标题】获取“MessageBodyWriter not found for media type=application/json”试图通过 JAX-RS Web 服务发送 JSON 对象【英文标题】:Obtaining "MessageBodyWriter not found for media type=application/json" trying to send JSON object through JAX-RS web service 【发布时间】:2014-01-12 18:26:04 【问题描述】:

我正在尝试通过 JAX-RS Web 服务发送 JSON 对象。 我的文件 web.xml 是:

<servlet>
 <description>JAX-RS Tools Generated - Do not modify</description>
 <servlet-name>JAX-RS Servlet</servlet-name>
 <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>it.notifire</param-value>
  </init-param>
  <init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>JAX-RS Servlet</servlet-name>
  <url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping>

模拟我要发送的对象的类是:

public class GPSCoordinate 

private float latitudine;
private float longitudine;

 public float getLatitudine() 
    return latitudine;

public void setLatitudine(float latitudine) 
     this.latitudine = latitudine;

public float getLongitudine() 
    return longitudine;

public void setLongitudine(float longitudine) 
    this.longitudine = longitudine;


根类资源是:

@Path("position")
public class Position 

    @Context
private UriInfo context;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public GPSCoordinate gethtml() 

        GPSCoordinate coord = new GPSCoordinate();
        coord.setLatitudine(90.45f);
        coord.setLongitudine(34.56f);

        return coord;
    

现在,当我尝试访问该服务时,我将浏览器指向以下链接

http://localhost:8080/Notifire/jaxrs/position

我收到以下错误:

消息 org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json

在我的 WEB-INF/lib 文件夹中,我有 jersey JAX-RS 实现的最新版本 (jaxrs-ri-2.5.jar) 和 jersey-json.jar 存档。

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

尝试将Genson 添加到您的类路径中,它将自动启用 JSON 支持。

Genson 是一个用于 json 和 java/scala 的数据绑定和流媒体库。它实现了 JAX-RS 的 MessageBodyReader/Writer 扩展点,让 jersey 能够自动检测 Genson 并将其用于 Json 解析/写入。

您可以找到更多关于Gensons integration with JaxRS (jersey & cie) 的信息。

【讨论】:

它是一个json的数据绑定和流式库。它还实现了 JAX-RS 的扩展点 MessageBodyReader/Writer 并使用 Java 服务加载器机制声明其 impl,允许 jersey(和其他)自动检测 Genson 并将其用于 Json 解析/写入。 你知道如何对 XML 做同样的事情吗?我需要从技术上理解你在说什么,你能推荐一本书或教程而不是泽西的用户指南(v2.5.1)吗?当我开始阅读它时,我迷路了! 如果你想生成 xml,here 是一个简单的例子,如何用球衣做到这一点。关于 Genson 是如何与球衣连接的,你可以阅读this,这是 java 提出的提供扩展点的基本机制 非常感谢。它对我有用。太棒了..很大的帮助 非常感谢。我仍然不明白为什么这有效,并且所有其他具有“自动发现功能”的库都不起作用,即使我尝试使用 maven 并自己在 web.xml 中注册类...【参考方案2】:

这就是我解决问题的方法。

使用杰克逊。添加了这些罐子

将这个类添加到我的项目中。代码的关键行标记为 IMPORTANT。

import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; <-- IMPORTANT
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;

//@javax.ws.rs.ApplicationPath("webresources")
public class MyApplicationConfig extends Application 

@Override
public Set<Class<?>> getClasses() 
    Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
    //addRestResourceClasses(resources);
    //resources.add(MultiPartFeature.class);
    //resources.add(JettisonFeature.class);
    return resources;


@Override
public Set<Object> getSingletons() 
    final Set<Object> instances = new HashSet<Object>();

    instances.add(new JacksonJsonProvider()); <--------- IMPORTANT
    return instances;

/**
 * Do not modify addRestResourceClasses() method.
 * It is automatically populated with
 * all resources defined in the project.
 * If required, comment out calling this method in getClasses().
 */
private void addRestResourceClasses(Set<Class<?>> resources) 
    //resources.add(org.glassfish.jersey.media.multipart.MultiPartProperties.Feature.MultiPartContextResolver.class);
    //resources.add(org.glassfish.jersey.media.multipart.MultiPartProperties.Feature.MultiPartContextResolver.class);




【讨论】:

【参考方案3】:

Jersey 支持“自动发现”功能,JSON 支持就是其中之一。为了启用它,你需要在你的路径中添加一个兼容的库,根据the docs

然而,虽然推荐的 jersey-media-json-processing 库由于某种原因在我的案例中未被识别,但 jersey-media-moxy 有:

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

2.15 是撰写本文时的最新版本。访问 maven central artifact page 查找当前版本。

【讨论】:

感谢您的建议。它解决了我的问题。我看到这个依赖在项目中添加了一些 org.eclipse.persistence.* 依赖。这些是必需的吗? 我浏览了代码。它使用 MOXyJsonProvider 类和该包中的其他类。所以我想这很好。 @Taher - 不客气 :) 至于依赖项 - 它们是 moxy 和 antlr 的传递依赖项 - 查看依赖项列表:mvnrepository.com/artifact/org.glassfish.jersey.media/… 查看包 org.eclipse.*,我的第一直觉告诉我,我是否添加了一些多余的 jar(这可能是 IDE 特定的,因为我使用 Eclipse 进行开发),但随后进行了一些挖掘以找到依赖项。也浏览了清除所有内容的依赖项列表。一直在尝试几件事,并找到了另一个使用 json-jackson 的替代解决方案。 org.glassfish.jersey.mediajersey-media-json-jackson2.17【参考方案4】:

转到https://jersey.java.net/documentation/2.5.1/user-guide.html#json

您需要完成您的课程.... JAXB 需要它,例如:

@XmlRootElement
public class MyJaxbBean 

    @XmlElement(name="king")
    public String name;

    @XmlTransient
    public int age;

    // several lines removed

【讨论】:

【参考方案5】:

我的根本原因略有不同。我花了一些时间调试 Jersey 源代码,结果发现由于我的 JAXB 类中缺少默认构造函数,它无法构造 JAXBContext。它发生在搜索合适的 MessageBodyWriter 期间,但未处理异常。

这里是对应的代码sn -p (MOXyJsonProvider:324):

try 
    Set<Class<?>> domainClasses = getDomainClasses(genericType);
    return getJAXBContext(domainClasses, annotations, mediaType, null);
 catch(JAXBException e) 
    return null;

因此,如果您在 POM 中有 Moxy JSON 依赖项,请仔细检查您的 JAXB 类是否有效。

我正在使用的版本:Jersey 2.19、Moxy 2.6.0。

【讨论】:

【参考方案6】:

使用客户端配置注册 JacksonJsonProvier 类,然后创建 Client 对象,这对我有用。下面是代码。

    ClientConfig config = new ClientConfig();
    config.register(JacksonJsonProvider.class);
    Client client = ClientBuilder.newClient(config);

【讨论】:

我认为这是大多数情况下的问题。如果自动注册不起作用,您应该尝试手动注册。【参考方案7】:

通过添加所有必需的杰克逊罐子,它对我有用。 添加了这些罐子

jackson-annotations-2.8.7.jar, jackson-core-2.8.7.jar jackson-databind-2.8.7.jar jackson-jaxrs-base-2.8.7.jar jackson-jaxrs-json-provider-2.8.3.jar jackson-module-jaxb-annotations-2.8.7.jar

【讨论】:

以上是关于获取“MessageBodyWriter not found for media type=application/json”试图通过 JAX-RS Web 服务发送 JSON 对象的主要内容,如果未能解决你的问题,请参考以下文章

js如何获取某一个元素,如果获取不到就继续获取,直到获取到后停止获取?

iOS ---------- 获取设备的各种信息

java反射获取属性值

Shell 获取路径

iOS 获取文件大小

根据日期字符串获取星期几,日期获取星期,时间获取星期,js获取星期