jsonnode deserialize array java json arraylist jackson

deserialize - No se puede deserializar la instancia de java.util.ArrayList fuera de VALUE_STRING



json to arraylist java (4)

Esta es la solución para mi vieja pregunta:

Implementé mi propio ContextResolver para habilitar la función 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; } }

Y en el web.xml registré mi paquete en la definición del 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>

... todo el resto está hecho de manera transparente por jersey / jackson.

Tengo un servicio REST construido con Jersey y desplegado en App Engine. El servicio REST implementa el verbo PUT que consume un tipo de aplicación / json. El enlace de datos es realizado por Jackson.

El verbo consume una relación de departamentos de empresa representada en JSON como

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

En el lado del cliente, uso gson para convertir la representación JSON en un objeto java. Luego, paso el objeto a mi servicio REST y funciona bien.

Problema:

Cuando mi representación JSON tiene solo un elemento en la colección

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

el servicio no puede deserializar el objeto.

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

Según informaron otros usuarios, la solución es agregar el indicador ACCEPT_SINGLE_VALUE_AS_ARRAY (por ejemplo, Jersey: no se puede deserializar la instancia de ArrayList fuera de String ). Sin embargo, no estoy controlando un ObjectMapper porque, en el lado del servicio, Jackson lo hace de forma transparente.

Pregunta:

¿Hay alguna forma de configurar ObjectMapper en el lado del servicio para habilitar ACCEPT_SINGLE_VALUE_AS_ARRAY? anotaciones? web.xml?

Detalles del código

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

El lado del servicio REST:

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

Lado del cliente:

... 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()); } ...


Establecer este atributo en la instancia de ObjectMapper funciona,

objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);


Para las personas que encuentran esta pregunta buscando el mensaje de error, también puede ver este error si cometen un error en sus anotaciones @JsonProperty , de manera que anoten una propiedad de tipo List con el nombre de un campo de un solo valor:

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


lo intentas

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

la llave cuadrada es el punto clave.