无法将java.util.ArrayList的实例反序列化为VALUE_STRING

我有一个使用Jersey构build的REST服务,并部署在AppEngine中。 REST服务实现了使用应用程序/ json媒体types的动词PUT。 数据绑定由Jackson执行。

动词使用以JSON表示的企业 – 部门关系

{"name":"myEnterprise", "departments":["HR","IT","SC"]} 

在客户端,我使用gson将JSON表示转换为一个java对象。 然后,我将该对象传递给我的REST服务,它工作正常。

问题:

当我的JSON表示在集合中只有一个项目

 {"name":"myEnterprise", "departments":["HR"]} 

该服务不能反序列化该对象。

 ATTENTION: /enterprise/enterprise: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token at [Source: org.mortbay.jetty.HttpParser$Input@5a9c5842; line: 1, column: 2 

正如其他用户所报告的,解决scheme是添加标志ACCEPT_SINGLE_VALUE_AS_ARRAY(例如Jersey:不能将StringList的实例反序列化为string )。 不过,我并不是在控制一个ObjectMapper,因为在服务方面它是由Jackson透露的。

题:

有没有办法在服务端configurationObjectMapper来启用ACCEPT_SINGLE_VALUE_AS_ARRAY? 注释? web.xml中?

代码细节

Java对象:

 @XmlRootElement public class Enterprise { private String name; private List<String> departments; public Enterprise() {} public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getDepartments() { return departments; } public void setDepartments(List<String> departments) { this.departments = departments; } } 

REST服务端:

  @PUT @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) @Path("/enterprise") public Response putEnterprise(Enterprise enterprise, @Context HttpServletRequest req){ ... } 

客户端:

 ... String jsonString = "{\"name\":\"myEnterprise\", \"departments\":[\"HR\"]}"; Enterprise enterprise = gson.fromJson(jsonString, Enterprise.class); System.out.println(gson.toJson(enterprise)); response = webResource .type(MediaType.APPLICATION_JSON) .put(ClientResponse.class,enterprise); if (response.getStatus() >= 400) { throw new RuntimeException("Failed : HTTP error code : " + response.getStatus()); } ... 

这是我的老问题的解决scheme:

我实现了我自己的ContextResolver,以启用DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAYfunction。

 package org.lig.hadas.services.mapper; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.ObjectMapper; @Produces(MediaType.APPLICATION_JSON) @Provider public class ObjectMapperProvider implements ContextResolver<ObjectMapper> { ObjectMapper mapper; public ObjectMapperProvider(){ mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); } @Override public ObjectMapper getContext(Class<?> type) { return mapper; } } 

在web.xml中,我将我的包注册到servlet定义中。

 <servlet> <servlet-name>...</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>...;org.lig.hadas.services.mapper</param-value> </init-param> ... </servlet> 

其余的都是由泽西/jackson透明地完成的。

你试试看

 [{"name":"myEnterprise", "departments":["HR"]}] 

方括号是关键。

将此属性设置为ObjectMapper实例的作品,

 objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); 

对于通过search错误消息来发现此问题的用户,如果您在@JsonProperty注释中犯了一个错误,则可以看到此错误,以便使用单值字段的名称对List type属性进行注释:

 @JsonProperty("someSingleValuedField") // Oops, should have been "someMultiValuedField" public List<String> getMyField() { // deserialization fails - single value into List return myField; }