假设 Jackson 是您的序列化程序,您可以将 ObjectMapper 配置为 WRAP_ROOT_VALUE。您可以在ContextResolver 中执行此操作。为了不为所有类型使用相同的配置,您可以使用两个不同的配置ObjectMappers,一个用于列表类,一个用于其余的。例如
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper> {
final ObjectMapper listMapper = new ObjectMapper();
final ObjectMapper defaultMapper = new ObjectMapper();
public ObjectMapperContextResolver() {
listMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
listMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
listMapper.registerModule(new JaxbAnnotationModule());
defaultMapper.registerModule(new JaxbAnnotationModule());
}
@Override
public ObjectMapper getContext(Class<?> type) {
if (type == MovieList.class) {
return listMapper;
}
return defaultMapper;
}
}
用于编组的MessageBodyWriter 将调用getContext 方法,传入它试图编组的类。根据结果,即将使用ObjectMapper。 WRAP_ROOT_VALUE 所做的是将根值包装在一个对象中,名称是 @JsonRootName 或 @XmlRootElement 中的值(假设 JAXB 注释支持已启用 - 请参阅 here)
测试:
@Path("/movies")
public class MovieResource {
@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response getMovieList() {
MovieList list = new MovieList();
list.add(new Movie("I Origins"));
list.add(new Movie("Imitation Game"));
return Response.ok(list).build();
}
}
C:\>curl -v -H "Accept:application/json" http://localhost:8080/api/movies
结果:
{
"movies" : [ {
"name" : "I Origins"
}, {
"name" : "Imitation Game"
} ]
}
更新
所以我注意到您的列表为protected。也许您以后可能想要扩展 MovieList 类。在这种情况下,这个
if (type == MovieList.class) {
return listMapper;
}
机器人是可行的。相反,您需要检查类型 isAssignableFrom
if (MovieList.class.isAssignableFrom(type)) {
return listMapper;
}