我如何定制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>