一尘不染

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

json

我有一个使用Jersey构建并部署在AppEngine中的REST服务。REST服务实现使用application/json媒体类型的动词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

正如其他用户报告的那样,解决方案是添加标记ACCEPT_SINGLE_VALUE_AS_ARRAY。但是,我无法控制,ObjectMapper因为在服务方面,它是由Jackson透明制造的。

题:

有没有一种方法可以ObjectMapper在服务端配置启用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());
}
...

阅读 658

收藏
2020-07-27

共1个答案

一尘不染

这是我的老问题的解决方案:

ContextResolver启用了自己的DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY功能以启用该功能。

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>

…其余所有工作都是由球衣/杰克逊透明完成的。

2020-07-27