如何自定义JAXB对象列表到JSON的序列化? [英] How can I customize serialization of a list of JAXB objects to JSON?

查看:63
本文介绍了如何自定义JAXB对象列表到JSON的序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Jersey to create a REST web service for a server component.

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

The JAXB-annotated object I want to serialize in a list looks like this:

@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资源来检索一个看起来像这样的发行版:

I have a REST resource to retrieve one distribution which looks like this:

@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资源来检索所有发行版的列表,如下所示:

I also have a REST resource to retrieve a list of all distributions, which looks like this:

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



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

I use a ContextResolver to customize JAXB serialization, which is currently configured like this:

@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资源都可以使用,以及上下文解析器。这是第一个输出的示例:

Both REST resources work, as well as the context resolver. This is an example of output for the first one:

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

这正是我想要的。这是列表输出的示例:

Which is exactly what I want. This is an example of output for the list:

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

这不是我想要的。

我不明白为什么有一个封闭的发布标签。我想在上下文解析器中使用 .rootUnwrapping(true)删除它,但显​​然只删除了另一个封闭标记。这是输出 .rootUnwrapping(false)

I don't understand why there is an enclosing distribution tag there. I wanted to remove it with .rootUnwrapping(true) in the context resolver, but apparently that only removes another enclosing tag. This is the output with .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"}]}}

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

I also had to configure .arrays("distribution") to always get a JSON array, even with only one element.

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

Ideally, I'd like to have this as an output:

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

我试图返回列表< XMLDistribution> XMLDistributionList (列表中的包装), XMLDistribution [] ,但我找不到aw ay以我所需的格式获得一个简单的JSON分发数组。

I tried to return a List<XMLDistribution>, a XMLDistributionList (wrapper around a list), a XMLDistribution[], but I couldn't find a way to get a simple JSON array of distributions in my required format.

我还尝试了 JSONConfiguration.natural()返回的其他符号 JSONConfiguration.mappedJettison()等,并且无法获得类似于我需要的任何内容。

I also tried the other notations returned by JSONConfiguration.natural(), JSONConfiguration.mappedJettison(), etc, and couldn't get anything resembling what I need.

有没有人知道是否可以配置JAXB来执行此操作?

Does anyone know if it is possible to configure JAXB to do this?

推荐答案

我找到了一个解决方案:替换JAXB JSON序列化程序,具有像Jackson这样表现更好的JSON序列化程序。简单的方法是使用jackson-jaxrs,它已经为你完成了它。该课程是JacksonJsonProvider。您所要做的就是编辑项目的web.xml,以便Jersey(或其他JAX-RS实现)扫描它。以下是您需要添加的内容:

I found a solution: replace the JAXB JSON serializer with a better behaved JSON serializer like Jackson. The easy way is to use jackson-jaxrs, which has already done it for you. The class is JacksonJsonProvider. All you have to do is edit your project's web.xml so that Jersey (or another JAX-RS implementation) scans for it. Here's what you need to add:

<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序列化,它的工作方式与列表和数组的预期方式相同。

And that's all there is to it. Jackson will be used for JSON serialization, and it works the way you expect for lists and arrays.

更长的方法是编写自己的自定义MessageBodyWriter,以生成application / json。下面是一个例子:

The longer way is to write your own custom MessageBodyWriter registered to produce "application/json". Here's an example:


@Provider
@Produces("application/json")
public class JsonMessageBodyWriter implements MessageBodyWriter {
    @Override
    public long getSize(Object obj, Class type, Type genericType,
            Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    @Override
    public boolean isWriteable(Class type, Type genericType,
            Annotation annotations[], MediaType mediaType) {
        return true;
    }

    @Override
    public void writeTo(Object target, Class type, Type genericType,
            Annotation[] annotations, MediaType mediaType,
            MultivaluedMap httpHeaders, OutputStream outputStream)
            throws IOException {        
        new ObjectMapper().writeValue(outputStream, target);
    }
}

您需要确保您的web.xml包含该包,至于上面的现成解决方案。

You'll need to make sure your web.xml includes the package, as for the ready-made solution above.

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

Either way: voila! You'll see properly formed JSON.

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

You can download Jackson from here: http://jackson.codehaus.org/

这篇关于如何自定义JAXB对象列表到JSON的序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆