强制JAX-RS将我的类序列化为JSON对象

我有一个类,它是一个内部列表的装饰器。 我想在我的JAX-RS服务中将此类用作DTO。 其代码如下:

@XmlRootElement(name = "movies") public class MoviesResponse implements List { @XmlElement(name = "movie") protected List movies; /* tons of delegate methods */ } 

我需要同时支持application / xml和application / json。 格式是固定的,它必须是

         

…在XML中,和

 { "movie": [ {},{} ] } 

…在JSON中。 XML工作得很好,但JSON看起来像这样:

 [{},{}] 

您可能怀疑,如果我没有实现List接口,它会生成我需要的格式。 所以我猜序列化器是聪明的,并将其视为List,从而将其序列化为一个数组。 但是我需要将它序列化为一个对象。 我该怎么做,实现List接口?

假设Jackson是您的序列化程序,您可以将ObjectMapper配置为WRAP_ROOT_VALUE 。 您可以在ContextResolver执行此操作。 因此,所有类型都不使用相同的配置,您可以使用两个不同的已配置ObjectMapper ,一个用于列表类,另一个用于其余类型。 例如

 @Provider public class ObjectMapperContextResolver implements ContextResolver { 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方法,传入它试图编组的类。 根据结果​​,即将使用的ObjectMapperWRAP_ROOT_VALUE作用是将根值包装在一个对象中,其名称是@JsonRootName@XmlRootElement的值(给定JAXB注释支持已启用 – 请参见此处 )

测试:

 @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" } ] }

UPDATE

所以我注意到你的列表被protected 。 也许你以后可能想要扩展MovieList类。 在这种情况下,这

 if (type == MovieList.class) { return listMapper; } 

将是可行的。 您需要检查类型isAssignableFrom

 if (MovieList.class.isAssignableFrom(type)) { return listMapper; }