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

时间:2016-05-16 08:57:29

标签: json rest 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响应

XML response in Postman

现在,我希望得到一个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日志中给出了以下错误:

  

SEVERE:找不到媒体类型= application / json的MessageBodyWriter,type = class java.util.ArrayList,genericType = java.util.List。

有人可以指导我如何获得JSON回复吗?

5 个答案:

答案 0 :(得分:9)

要将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>

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

有关详细信息,请查看泽西岛documentation

答案 1 :(得分:2)

我现在对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-method。只有这个字段才会出现在JSON中。
  4. 我经常做的是添加第二个构造函数来获取传入的运行时对象,并将所有字段设置为直接公开。因此,我不需要也不需要set方法。解决方案是使用 @XmlElement
  5. 注释get方法
  6. 我说你需要一个空/默认构造函数吗?花了我三个小时来找出为什么class1工作正常,class2得到了MessageBodyWriter错误。我忘记了构造函数。 Grrrrr。
  7. 当类配置正常但你的一个字段返回一个无法序列化的类型时,你会得到同样的错误(我相信)。
  8. 我相信有一个案例,其中类注释 @XmlRootElement 导致了该错误。不确定,但我目前几乎没有使用该注释。
  9. 如果您将List作为要转换为Json数组的元素之一,JAXB将使用myAbstract类进行序列化。不是很有用,你想要实际对象被序列化。但是JAXB应该如何知道谁实现/扩展了这个类呢?你必须告诉注释@XmlSeeAlso。因此,MyAbstract类获取类注释 @XmlSeeAlso({MyConcrete1.class,MyConcrete2.class})。至少Moxy会添加一个额外的类型字段,告诉消费者它是哪个类。完全有道理。
  10. 虽然您可以返回 userList ,但更好的选择是返回 Response.ok()。entity(userList).build();然后你也可以返回错误。逻辑上它是一样的。
  11. 注意您使用的是哪种数据类型。字符串很好,ArrayList也是,Hashtable没有。取决于您使用的序列化程序。
  12. 我希望这有助于其他人。

答案 2 :(得分:1)

您需要在类路径上使用json序列化程序才能使其正常工作。

只需添加杰克逊和泽西将在作家中使用此功能。 例如。如果您使用的是maven,请将其添加到pom.xml

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

答案 3 :(得分:0)

您的xml正在运行,因此我假设您的@XmlRootElement课程中有User个注释。

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

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

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

或为maven用户

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

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

答案 4 :(得分:0)

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