【问题标题】:How to make Jersey/Jackson serialize empty list; single element list as an array如何让 Jersey/Jackson 序列化空列表;单个元素列表作为数组
【发布时间】:2012-01-03 03:07:06
【问题描述】:

使用 Jersey 和 Jackson 创建 REST 接口,当列表字段中有 0 或 1 个元素时,如何将列表字段序列化为列表。例如:

@XmlRootElement(name="foo")
public class Foo {
  @XmlElement
  public List<Bar> getBars() {
    return this.bars;
  }
}

@Path("foo")
public FooResource {
  @GET
  public Foo getFoo() {
    return theFoo;
  }
}

当 bar 没有元素时,结果序列化为null,当它包含单个元素时,它序列化为该元素,而不是包含单个元素的数组。有没有办法让这些总是序列化为数组?

作为参考,我使用的是 Jersey 1.10 和 Jackson 1.9.2。

【问题讨论】:

    标签: java json jersey jackson


    【解决方案1】:

    是的,我们也面临同样的问题。 Jackson 无法将具有 0 或单个元素的列表序列化为 json 数组。所以我们尝试使用 Json 的 ObjectMapper 将 POJO 对象转换为 String。它会将 java List 序列化为 json 数组,而不考虑 List 中的元素数量(0 或 1 或 > 0)。代码如下所示:

     request = new ObjectMapper().writeValueAsString(pojo);
    

    其中请求是对象类型。这不会影响响应。你可以试一试。

    【讨论】:

      【解决方案2】:

      我设法在最近的 Jersey json 库(v1.14 Sep 2012)中解决了 JSON 数组“错误”。秘密成分是 JSONConfiguration 和 ContextResolver 魔术。请参阅我的以下帖子,它有一个完整的代码示例,自定义的 ContextResolver 和 rest Application 类乍一看可能有点模糊。

      How to serialize Java primitives using Jersey REST

      基元和零或单元素列表数组已正确序列化为 JSON 文档。

      【讨论】:

        【解决方案3】:

        我很确定您实际上并没有使用 Jackson(JSON 序列化的“POJO”变体),因为 Jackson 不会将单元素数组或列表转换为其他任何东西。因此,您可能正在使用一种传统的输出方法(如 jettison);这意味着如果您将系统配置为使用 POJO 映射,它应该可以正常工作。

        【讨论】:

        • 你是对的,杰克逊的配置不正确。除了将 'org.codehaus.jackson.jaxrs' 添加到 com.sun.jersey.config.property.packages 初始化参数之外,还有更明确​​的方法来配置 Jackson 以在 Jersey 中使用吗?
        • 可以使用标准的 JAX-RS 注册机制从 jax-rs jar (JacksonJsonProvider) 显式注册提供程序类,有关详细信息,请参阅 wiki.fasterxml.com/JacksonFAQ#JAX-RS(例如)。
        【解决方案4】:

        我很久以前写过一篇关于强制 Jersey 正确序列化单个元素数组的博客文章,不确定它现在是否过时(从 2010 年中期开始!),but it might be of use.

        请注意 Brill Pappin 在博客上的博客评论,该评论展示了一种不同的方法,这意味着升级您正在使用的 Jettison 库。

        简而言之,您可以编写一个看起来有点像的自定义 JaxbContextResolver:

        @Provider
        @Component
        public class JAXBContextResolver implements ContextResolver {
        
            private JAXBContext context;
        
            public JAXBContextResolver() throws Exception {
                MappedBuilder builder = JSONConfiguration.mapped();
                builder.arrays("invite");
                builder.rootUnwrapping(true);
                this.context = new JSONJAXBContext(builder.build(), Payload.class);
            }
        
            public JAXBContext getContext(Class objectType) {
                return (Payload.class.equals(objectType)) ? context : null;
            }
        }
        

        为了清楚起见,我的有效载荷类看起来有点像

        @XmlRootElement(name = "response")
        @XmlAccessorType(XmlAccessType.FIELD)
        public class Payload {
        
            @XmlElement(name = "invite")
            List invites;
        
            ... etc.
        

        关于停止 Jackson 将 bean 属性序列化为 null,请参阅 my previous answer here, about using annotations to change that behaviour.

        【讨论】:

        • 好的。我创建了一个 ContextResolver,它使用反射来更改我的数据 bean 中所有列表的序列化行为。对于我的口味,这仍然感觉有点太暴力了。如果有更好的方法,仍然对它感兴趣。
        • 从答案中查看 Brill Pappin 对我的博客链接的评论,他描述了一种解决方案,您可以升级 Jackson 所依赖的 Jettison 版本。
        • 嗯,您可能是指“Jersey 所依赖的 Jettison”(对于 JSON 绑定方法之一)。杰克逊不依赖 Jettison(反之亦然)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-06
        • 1970-01-01
        • 2011-12-28
        • 1970-01-01
        • 1970-01-01
        • 2020-11-14
        • 2018-09-25
        相关资源
        最近更新 更多