首页 文章

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

提问于
浏览
3

我正在尝试使用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,类型=类java.util.ArrayList,genericType = java.util.List的MessageBodyWriter .

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

4 回答

  • 0

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

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

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

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

  • 1

    我现在对JAXB绑定感到有点不高兴,所以让我在这里总结一下我的发现 - 如果我说些愚蠢的话,请纠正我:

    • 当然你必须有一个库来进行JSON(反)序列化,在我的例子中它是Moxy .

    • 你必须告诉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 .

    • 默认情况下,JAXB适用于POJO . 所以你需要一个没有参数的构造函数,一个get-和set-method . 只有这个字段才会出现在JSON中 .

    • 我经常做的是添加第二个构造函数来获取传入的运行时对象,并将所有字段设置为直接公开 . 因此,我不需要也不需要set方法 . 解决方案是使用@XmlElement注释get方法 .

    • 我说你需要一个空/默认构造函数吗?花了我三个小时来找出为什么class1工作正常,class2得到了MessageBodyWriter错误 . 我忘记了构造函数 . Grrrrr .

    • 当类配置正常但你的一个字段返回一个无法序列化的类型时,你得到同样的错误(我相信) .

    • 我相信有一个案例,其中类注释@XmlRootElement导致该错误 . 不确定,但我目前几乎没有使用该注释 .

    • 如果您将List作为要转换为Json数组的元素之一,JAXB将使用myAbstract类进行序列化 . 不是很有用,你想要实际对象被序列化 . 但是JAXB应该如何知道谁实现/扩展了这个类呢?你必须告诉注释@XmlSeeAlso . 因此,MyAbstract类获取类注释@XmlSeeAlso({MyConcrete1.class,MyConcrete2.class}) . 至少Moxy会添加一个额外的类型字段,告诉消费者它是哪个类 . 完全有道理 .

    • 虽然你可以返回userList,但更好的选择是返回Response.ok() . entity(userList).build();然后你也可以返回错误 . 逻辑上它是一样的 .

    • 注意您使用的是哪种数据类型 . 字符串很好,ArrayList也是,Hashtable没有 . 取决于您使用的序列化程序 .

    我希望这有助于其他人 .

  • 1

    你的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>
    

    Also it should have a no argument constructor

相关问题