繁体   English   中英

使用 Jersey 在 REST Web 服务中返回 JSON 时,找不到 media type=application/json 的 MessageBodyWriter

[英]MessageBodyWriter not found for media type=application/json when returning JSON in REST web service with Jersey

我正在尝试使用 Jersey 创建一个非常简单的 REST 服务。 这是服务代码

@Path("/UserService")
public class UserService {

    @GET
    @Path("/users")
    @Produces(MediaType.APPLICATION_XML)
    public List<User> getUsers() {
        User user = new User(1, "Thomas", "Greene");
        List<User> userList = new ArrayList<User>();
        userList.add(user);
        return userList;
    }
}

当我通过 Postman 运行它时,它会返回一个 XML 响应

Postman 中的 XML 响应

现在,我想得到一个 JSON 响应。 因此,我将 mediatype 更改为application/json

@Path("/UserService")
public class UserService {

    @GET
    @Path("/users")
    @Produces(MediaType.APPLICATION_JSON)
    public List<User> getUsers(){ 
        User user = new User(1, "Thomas", "Greene");
        List<User> userList = new ArrayList<User>();
        userList.add(user);
        return userList;
   }    
}

它在Tomcat日志中给了我以下错误:

严重:找不到 Media type=application/json、type=class java.util.ArrayList、genericType=java.util.List 的 MessageBodyWriter。

有人可以指导我如何获得 JSON 响应吗?

要将 Jackson 2.x 用作您的 JSON 提供程序,您需要将jersey-media-json-jackson模块添加到您的pom.xml文件中:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.22.2</version>
</dependency>

然后在您的Application / ResourceConfig子类中注册JacksonFeature

有关更多详细信息,请查看 Jersey 文档

你需要在你的类路径上有一个 json 序列化器来完成这项工作。

只需添加 jackson 和 jersey 将在作家中使用它。 例如,如果您使用的是 maven,请将其添加到 pom.xml

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-core</artifactId>
  <version>2.7.4</version>
</dependency>

目前我对 JAXB 绑定也有点不高兴,因此让我在这里总结一下我的发现 - 如果我说一些愚蠢的话,请纠正我:

  1. 当然,您必须有一个库来进行 JSON(反)序列化,在我的情况下它是 Moxy。
  2. 您必须告诉 JAXB 它应该支持哪些类。 有多种方法可以做到这一点,最简单的似乎是在与您的类匹配的目录中添加一个jaxb.properties文件,其唯一内容是文本javax.xml.bind.context.factory=org.eclipse.persistence.jaxb .JAXBContextFactory 对于目录,我的意思是,如果您的类在src/main/java目录中,并且有com.pkg1.entities包,则将此文件添加到src/main/resources 中,然后将其添加为com/pkg1/entities/jaxb.properties
  3. 默认情况下,JAXB 适用于 POJO。 所以你需要一个没有参数的构造函数,一个get-和一个set-方法。 只有这样,该字段才会出现在 JSON 中。
  4. 我经常做的是添加第二个构造函数来获取传入的运行时对象并将所有字段设置为直接公开。 因此我不需要也不想要设置方法。 解决方案是使用@XmlElement注释 get 方法。
  5. 我说你需要一个空的/默认的构造函数吗? 我花了三个小时才找出为什么 class1 工作正常,而 class2 收到 MessageBodyWriter 错误。 我忘记了构造函数。 咕噜噜。
  6. 当类配置良好但其中一个字段返回无法序列化的类型时,您会遇到相同的错误(我相信)。
  7. 我相信有一种情况是类注释@XmlRootElement导致了该错误。 不确定,但我目前几乎不使用该注释。
  8. 如果您有一个 List 作为要转换为 Json 数组的元素之一,JAXB 将使用 myAbstract 类进行序列化。 不是很有用,您希望序列化实际对象。 但是 JAXB 如何知道谁实现/扩展了这个类? 你必须用@XmlSeeAlso 注释来说明。 所以 MyAbstract 类得到一个类注释@XmlSeeAlso({MyConcrete1.class, MyConcrete2.class}) 至少 Moxy 确实添加了一个额外的类型字段,告诉消费者它是哪个类。 完全有道理。
  9. 虽然你可以返回userList更好的选择是返回Response.ok().entity(userList).build() ; 然后你也可以返回错误。 逻辑上是一样的。
  10. 注意您使用的数据类型。 String 可以,ArrayList 也可以,Hashtable 不行。 也取决于您使用的序列化程序。

我希望这对其他人有帮助。

您的 xml 正在运行,所以我假设您的User类中有@XmlRootElement注释。

问题是,它知道如何使用注释@XmlRootElement将其转换为 xml,但它不知道如何将其转换为 JSON。

因此,为了使其使用相同的 xml 注释(即@XmlRootElement )将所有内容转换为 JSON,我们可以添加

jersey-media-moxy-<whatever version>.jar

或者对于 maven 用户

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

它也应该有一个无参数构造函数

我尝试了大量这些依赖项,但没有一个适用于我的 Jersey3 版本。 我需要做的是将 Arraylist 变成一个实际的数组。 我用toArray()管理了这个,它开始正确序列化!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM