2013-01-14 45 views
10

我有一个基于json的REST Web服务使用: Jetty,Jersey,Jersey-JSON使用Jackson实现。泽西岛:无法反序列化ArrayList的实例字符串

我的一个方法收到一个Person实例,该实例有一个字段类型列表<字符串>。 即:

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

但这些都不解决问题。

预先感谢您!

回答

11

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

我所做的:

  1. 使用杰克逊
  2. 队杰克逊提供商使用
  3. 定义自定义解串器
  4. 激活ACCEPT_SINGLE_VALUE_AS_ARRAY标志
  5. 修复依赖

故事:

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

我改成了使用杰克逊

<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

这让我的球衣使用杰克逊,但问题仍然存在;杰克逊不能解串行数组呢。

我强迫的杰克逊提供商用法:

<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

做这一切仍然没有奏效后...

After一些更多的搜索时间,我发现:

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或抛弃新泽西能力。

题外话,可能有人很有趣:

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

+0

感谢队友,下面这行解决了我的问题:objectMapper = new ObjectMapper()。configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY,true); – mojsilo

+0

@mojsilo你在哪里把 ** objectMapper = new ObjectMapper()。configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY,true); ** ? – Luke

+0

我已经把它放在服务的构造函数 mapper.configure(\t \t org.codehaus.jackson.map.DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY,true); – mojsilo

1

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

+1

谢谢你这样做!但我想解决这个问题在服务器端。更新我的问题是明确的。 –

+0

你会在客户端添加** JSONConfiguration.mapped()。arrays(“names”)。build()** ?当您构建请求时,但在发送之前? – Luke

1

它为我加@JsonSerialize到类

@JsonSerialize 
Public class Person { 
    List<String> names; 
} 
0
{"results": {"place": {"lang": "en-US","woeid": "2168606"}}} 

&

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

这种类型的使用雅虎的地方API

1

时怎么办?你可以在注解类,域或方法级使用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; 
}