无法将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; }