我如何定制JSON对象的序列化为JSON?

我正在使用Jersey为服务器组件创buildREST Web服务。

我要在列表中序列化的JAXB注释的对象如下所示:

@XmlRootElement(name = "distribution") @XmlType(name = "tDistribution", propOrder = { "id", "name" }) public class XMLDistribution { private String id; private String name; // no-args constructor, getters, setters, etc } 

我有一个REST资源来检索一个分配,看起来像这样:

 @Path("/distribution/{id: [1-9][0-9]*}") public class RESTDistribution { @GET @Produces("application/json") public XMLDistribution retrieve(@PathParam("id") String id) { return retrieveDistribution(Long.parseLong(id)); } // business logic (retrieveDistribution(long)) } 

我也有一个REST资源来检索所有发行版的列表,如下所示:

 @Path("/distributions") public class RESTDistributions { @GET @Produces("application/json") public List<XMLDistribution> retrieveAll() { return retrieveDistributions(); } // business logic (retrieveDistributions()) } 

我使用ContextResolver来自定义JAXB序列化,目前configuration如下:

 @Provider @Produces("application/json") public class JAXBJSONContextResolver implements ContextResolver<JAXBContext> { private JAXBContext context; public JAXBJSONContextResolver() throws Exception { JSONConfiguration.MappedBuilder b = JSONConfiguration.mapped(); b.nonStrings("id"); b.rootUnwrapping(true); b.arrays("distribution"); context = new JSONJAXBContext(b.build(), XMLDistribution.class); } @Override public JAXBContext getContext(Class<?> objectType) { return context; } } 

这两个REST资源以及上下文parsing器都可以工作。 这是第一个输出的例子:

 // path: /distribution/1 {"id":1,"name":"Example Distribution"} 

这正是我想要的。 这是列表输出的一个例子:

 // path: /distributions {"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]} 

这不是我想要的。

我不明白为什么在那里有一个封闭的distribution标签。 我想在上下文parsing器中使用.rootUnwrapping(true)将其删除,但显然只删除了另一个封闭标签。 这是.rootUnwrapping(false)的输出:

 // path: /distribution/1 {"distribution":{"id":1,"name":"Example Distribution"}} // not ok // path: /distributions {"xMLDistributions":{"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]}} 

我还必须configuration.arrays("distribution")总是得到一个JSON数组,即使只有一个元素。

理想情况下,我想把这个作为输出:

 // path: /distribution/1 {"id":1,"name":"Example Distribution"} // currently works // path: /distributions [{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}] 

我试图返回一个List<XMLDistribution> ,一个XMLDistributionList (列表的包装),一个XMLDistribution[] ,但我找不到一种方法来得到我需要的格式的简单的分布的JSON数组。

我也尝试了由JSONConfiguration.natural()JSONConfiguration.mappedJettison()等返回的其他符号,并不能得到任何类似我需要的东西。

有谁知道是否有可能configurationJAXB来做到这一点?

我find了一个解决scheme:将JAXB JSON序列化程序replace为jackson更好的JSON序列化程序。 简单的方法是使用jackson-jaxrs,它已经为你做了。 这个类是JacksonJsonProvider。 您只需编辑项目的web.xml,以便Jersey(或其他JAX-RS实现)进行扫描。 以下是您需要添加的内容:

 <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>your.project.packages;org.codehaus.jackson.jaxrs</param-value> </init-param> 

这就是它的一切。 jackson将用于JSON序列化,它的工作方式你期望的列表和数组。

编写自己定制的MessageBodyWriter来生成“application / json”的方法就更长了。 这是一个例子:

 @Provider
 @Produces( “应用程序/ JSON”)
公共类JsonMessageBodyWriter实现MessageBodyWriter {
     @覆盖
     public long getSize(Object obj,Class type,Type genericType,
            注释[]注释,MediaType mediaType){
        返回-1;
     }

     @覆盖
    公共布尔isWriteable(types,typesgenericType,
            注释标注[],MediaType mediaType){
        返回true;
     }

     @覆盖
     public void writeTo(Object target,Class type,Type genericType,
            注释[]注释,MediaType mediaType,
            多值图httpHeaders,OutputStream outputStream)
            抛出IOException {        
         new ObjectMapper()。writeValue(outputStream,target);
     }
 }

您需要确保您的web.xml包含该包,就像上面的现成解决scheme一样。

无论哪种方式:瞧! 你会看到正确的JSON。

你可以从这里下载Jackson: http : //jackson.codehaus.org/

Jonhatan的答案很好,对我来说非常有用。

只是升级:

如果你使用Jackson的版本2.x(例如版本2.1),类是com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider,因此web.xml是:

 <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>your.project.packages;com.fasterxml.jackson.jaxrs.json</param-value> </init-param>