本文介绍了无法反序列化的java.util.ArrayList实例出来VALUE_STRING的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有泽西构建和部署在AppEngine上REST服务。其余的服务实现了动词PUT消耗的应用程序/ json的媒体类型。数据绑定是由杰克逊进行的。

动词消耗了企业部门的关系再在JSON psented $ P $为

  {名:MYENTERPRISE,部门:HR,IT,SC]}

在客户端,我用GSON到JSON重新presentation转换为Java对象。然后,我的对象传递给我的REST服务,它工作正常。

问题:

当我重新JSON presentation具有集合中只有一个项目

  {名:MYENTERPRISE,部门:HR]}

该服务无法反序列化对象。

 注意:/企业/企业:组织codehaus.jackson.map.JsonMappingException:
在无法反序列化的java.util.ArrayList实例出来VALUE_STRING令牌
[来源:org.mortbay.jetty.HttpParser$Input@5a9c5842;行:1,列:2

据报道由其他用户,解决的办法是添加标志ACCEPT_SINGLE_VALUE_AS_ARRAY(例如,Jersey:无法反序列化ArrayList的实例,从字符串的)。然而,由于在服务方面,它都将透明的杰克逊做我不是一个控制ObjectMapper。

问:

有没有在服务端配置ObjectMapper使ACCEPT_SINGLE_VALUE_AS_ARRAY的方法吗?注解? web.xml中?

code详情

Java对象:

  @XmlRootElement
公共类企业{
    私人字符串名称;
    私人列表<串GT;部门;    公共企业(){}    公共字符串的getName(){
        返回名称;
    }
    公共无效setname可以(字符串名称){
        this.name =名称;
    }
    公开名单<串GT; getDepartments(){
        返回部门;
    }
    公共无效setDepartments(列表<串GT;部门){
        this.departments =部门;
    }
}

REST服务端:

  @PUT
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    @Path(/企业)
    市民反应putEnterprise(企业企业,
            @Context HttpServletRequest的REQ){
         ...
    }

客户端:

  ...
字符串jsonString ={\\名称\\:\\MYENTERPRISE \\,\\部门\\:[\\HR \\]};
企业企业= gson.fromJson(jsonString,Enterprise.class);
的System.out.println(gson.toJson(企业));
响应= webResource
           .TYPE(MediaType.APPLICATION_JSON)
           。把(ClientResponse.class,企业);
如果(response.getStatus()> = 400){
        抛出新的RuntimeException(失败:HTTP错误code:+ response.getStatus());
}
...


解决方案

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

我实现我自己的ContextResolver为了使DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY功能。

 包org.lig.hadas.services.mapper;进口javax.ws.rs.Produces;
进口javax.ws.rs.core.MediaType;
进口javax.ws.rs.ext.ContextResolver;
进口javax.ws.rs.ext.Provider;。进口组织codehaus.jackson.map.DeserializationConfig;
。进口组织codehaus.jackson.map.ObjectMapper;@Produces(MediaType.APPLICATION_JSON)
@Provider
公共类ObjectMapperProvider实现ContextResolver< ObjectMapper>
{
   ObjectMapper映射;   公共ObjectMapperProvider(){
       映射器=新ObjectMapper();
       mapper.configure(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY,真);
   }
   @覆盖
   公共ObjectMapper的getContext(类<>类型){
       返回映射器;
   }
}

和在web.xml我注册了我的包入servlet定义...

 <&servlet的GT;
    < servlet的名称> ...< / servlet的名称>
    <的servlet类> com.sun.jersey.spi.container.servlet.ServletContainer< / servlet的类>
    <初始化参数>
        <参数-名称>&com.sun.jersey.config.property.packages LT; /参数 - 名称>
        <参数值> ...; org.lig.hadas.services.mapper< /参数值>
    < /初始化参数>
    ...
< / servlet的>

...其余全部是透明球衣/杰克逊完成。

I have a REST service built with Jersey and deployed in the AppEngine. The REST service implements the verb PUT that consumes an application/json media type. The data binding is performed by Jackson.

The verb consumes an enterprise-departments relation represented in JSON as

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

In the client side, I use gson to convert the JSON representation into a java object. Then, I pass the object to my REST service and it works fine.

Problem:

When my JSON representation has only one item in the collection

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

the service cannot deserialize the object.

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

As reported by other users, the solution is to add the flag ACCEPT_SINGLE_VALUE_AS_ARRAY (e.g., Jersey: Can not deserialize instance of ArrayList out of String). Nevertheless, I am not controlling an ObjectMapper because in the service side it is transparently made by Jackson.

Question:

Is there a way to configure the ObjectMapper on the service side to enable ACCEPT_SINGLE_VALUE_AS_ARRAY? annotations? web.xml?

Code details

Java object:

@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;
    }
}

The REST service side:

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

Client side:

...
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());
}
...
解决方案

This is the solution for my old question:

I implemented my own ContextResolver in order to enable the DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY feature.

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

And in the web.xml I registered my package into the servlet definition...

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

... all the rest is transparently done by jersey/jackson.

这篇关于无法反序列化的java.util.ArrayList实例出来VALUE_STRING的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 05:37