Jersey:无法从String中反序列化ArrayList的实例

时间:2013-01-14 13:44:19

标签: java rest jersey jackson jax-rs

我使用以下方法实现了基于json的REST Web服务: Jetty,Jersey,Jersey-JSON使用Jackson。

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

Public class Person {
    List<String> names;
}

如果我用一系列名字来称呼它,一切正常! e.g:

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

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

{ "names" : "Jhon" } 

当我尝试使用单个值调用服务时,我得到一个例外:

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

问题:

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

-

我已经读过:

Jackson deserialization - with contained ArrayList<T>

How can I customize serialization of a list of JAXB objects to JSON?

这是指最后一个答案:

Jersey client can not deserializable json services - exception(can not deserialize instance)

Jaxb json missing brackets for one element array

但这些都没有解决问题。

提前谢谢!

5 个答案:

答案 0 :(得分:11)

经过漫长的一天,另一个......在阅读了很多维基和常见问题后,它终于有效了。

我做了什么:

  1. 使用杰克逊
  2. 强制杰克逊供应商使用
  3. 定义自定义反序列化程序
  4. 激活ACCEPT_SINGLE_VALUE_AS_ARRAY标志
  5. 修复依赖关系
  6. 故事:

    我使用的是泽西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;
        }
    }
    

    为了做到这一点:

    Customizing-ObjectMapper

    完成所有这些后仍然无法正常工作......

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

    Jackson 2.0 with Jersey 1.12

    讨论依赖问题 ..

    这引起了我的疑问,泽西岛v1.13 附带杰克逊v1.9.2我需要杰克逊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>
    

    参考:

    jackson-jaxrs-json-provider

    注意:此更改会移除泽西岛使用Jaxb或jettison的能力。

    非主题,对某些人来说可能很有趣:

    Configure Jersey/Jackson to NOT use @XmlElement field annotation for JSON field naming

答案 1 :(得分:3)

您可以使用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;
}

答案 2 :(得分:1)

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

答案 3 :(得分:1)

通过将@JsonSerialize添加到类

,它对我有用
@JsonSerialize
Public class Person {
    List<String> names;
}

答案 4 :(得分:1)

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

&安培;

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

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