13

我有一个基于 json 的 REST Web 服务,使用:Jetty、Jersey、Jersey-JSON 使用 Jackson 实现。

我的一个方法接收一个 Person 实例,它有一个 List<String> 类型的字段。IE:

Public class Person {
    List<String> names;
}

如果我用一组名称调用它,一切正常!例如:

{ "names" : [ "Jhon", "Doe" ] }

但是如果这个人只有一个名字,我的客户会创建一个值元素,例如:

{ "names" : "Jhon" } 

当我尝试使用单个值调用服务时,出现异常:

Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token

问题:

我应该如何创建/配置我的 Web 服务,以便能够在数组字段作为单个元素发送给我时对其进行反序列化。

--

我已经读过:

Jackson 反序列化 - 包含 ArrayList<T>

如何自定义将 JAXB 对象列表序列化为 JSON?

这指的是最后一个答案:

Jersey 客户端无法反序列化 json 服务 - 异常(无法反序列化实例)

Jaxb json 缺少一个元素数组的括号

但这些都不能解决问题。

先感谢您!

4

5 回答 5

14

经过漫长的一天,又一个......在阅读了大量的维基和常见问题解答之后,它终于起作用了。

我做了什么:

  1. 使用杰克逊
  2. 强制使用 Jackson 提供程序
  3. 定义自定义反序列化器
  4. 激活 ACCEPT_SINGLE_VALUE_AS_ARRAY 标志
  5. 修复依赖关系

故事:

我使用的是 Jersey 1.13,它默认使用(我相信)jaxb。

我将其更改为使用杰克逊

<init-param>
    <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
    <param-value>true</param-value>
</init-param>

如所述:

https://stackoverflow.com/a/13895768/660990

这使我的球衣使用杰克逊,但问题仍然存在;jackson 还不能对数组进行反序列化。

我强迫使用杰克逊提供者

<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>

https://stackoverflow.com/a/3143214/660990

这是一个必要的步骤,但还不够。有必要激活ACCEPT_SINGLE_VALUE_AS_ARRAY标志。

ObjectMapper objectMapper;
objectMapper = new ObjectMapper().configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

我需要定义自定义反序列化器

public class MyResolver implements ContextResolver<ObjectMapper> {

@Override
    public ObjectMapper getContext(final Class<?> objectType) {
        ...            
        return objectMapper;
    }
}

为了做到这一点:

定制-ObjectMapper

做完这一切后,它仍然没有工作......

经过一段时间的搜索,我发现:

杰克逊 2.0 和泽西 1.12

这讨论了依赖问题..

这解决了我的问题,Jersey v1.13附带Jackson v1.9.2 我需要 Jackson v2.0

我删除了 jersey-json 的依赖项,因为它包含 jackson 1.9.2:

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
</dependency>

并直接声明依赖:

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
</dependency>

参考:

杰克逊-jaxrs-json-提供者

注意:此更改删除了 Jersey 使用 Jaxb 或 jettison 的能力。

题外话,对某人来说可能很有趣:

将 Jersey/Jackson 配置为不使用 @XmlElement 字段注释进行 JSON 字段命名

于 2013-01-18T16:07:11.253 回答
5

您可以使用JsonFormat注释在类、字段或方法级别执行此操作

@JsonFormat(with = Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
protected List<String> list;

public List<String> getList() {
    return list;
}

public void setList(List<String> list) {
    this.list = list;
}
于 2016-11-16T12:26:33.800 回答
1

本页的示例 5.10 和 5.11解释了您的确切问题。您可以配置 JSON 构建器以强制为单项列表创建数组,如下所示: JSONConfiguration.mapped().arrays("names").build().

于 2013-01-14T13:51:13.693 回答
1

通过将@JsonSerialize 添加到课程中,它对我有用

@JsonSerialize
Public class Person {
    List<String> names;
}
于 2014-09-30T22:14:32.497 回答
1
{"results": {"place": {"lang": "en-US","woeid": "2168606"}}}

&

{"results": {"place": [{"lang": "en-US","woeid": "2168606"}, {"lang": "en-US","woeid": "2168606"}]}}

这种类型怎么办......使用yahoo place api时

于 2015-08-13T13:27:05.707 回答