我正在尝试使用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响应 . 所以,我将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 回答
您需要在类路径上使用json序列化程序才能使其正常工作 .
只需添加 Jackson 和球衣将在作家中使用它 . 例如 . 如果您使用的是maven,请将其添加到pom.xml中
要将Jackson 2.x用作JSON提供程序,您需要将jersey-media-json-jackson模块添加到
pom.xml
文件中:然后在Application / ResourceConfig子类中注册JacksonFeature .
有关更多详细信息,请查看Jersey documentation .
我现在对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没有 . 取决于您使用的序列化程序 .
我希望这有助于其他人 .
你的xml正在工作,所以我假设你的
User
类中有@XmlRootElement
注释 .问题是,它知道如何使用注释
@XmlRootElement
将其转换为xml,但它不知道如何将其转换为JSON .因此,为了使所有内容都转换为具有相同xml注释(即
@XmlRootElement
)的JSON,我们可以添加jersey-media-moxy-<whatever version>.jar
或者对于maven用户
Also it should have a no argument constructor