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

qco9c6ql  于 2023-10-21  发布在  其他
关注(0)|答案(6)|浏览(179)

我正在尝试使用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响应

现在,我想得到一个JSON响应。因此,我将媒体类型更改为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:对于media type=application/json,type=class java.util.ArrayList,genericType= java.util. List,找不到MessageBodyWriter。
有人能教我如何得到一个JSON响应吗?

p8h8hvxi

p8h8hvxi1#

要使用Jackson2.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文档。

fcy6dtqo

fcy6dtqo2#

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

yzuktlbb

yzuktlbb3#

你需要一个json序列化器在你的类路径上来使它工作。
只要加上Jackson和泽西将使用这个作家。例如,如果您正在使用maven,请将其添加到pom.xml文件中。

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

slsn1g294#

你的xml是工作的,所以我假设你在你的User类中有@XmlRootElement注解。
问题是,它知道如何用注解@XmlRootElement将其转换为xml,但不知道如何将其转换为JSON。
因此,为了使它将所有内容转换为JSON,我们可以添加相同的xml注解(即@XmlRootElement),
jersey-media-moxy-<whatever version>.jar
或者对于maven用户

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

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

3qpi33ja

3qpi33ja5#

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

wh6knrhe

wh6knrhe6#

真实的问题是你需要把你的List放在一个类中,试试这个:

public class UserListClass() {
  private List<User> userList = new ArrayList<User>();

  public List<User> getUserList() { return userList; }
  public setUserList(List<User> userList) { this.userList = userList; }
}

你的代码是这样的:

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

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

相关问题