Jersey: no se puede deserializar la instancia de ArrayList fuera de cadena

Tengo un servicio web REST basado en JSON implementado usando: Jetty, Jersey, Jersey-JSON usando Jackson.

Uno de mis métodos recibe una instancia de Persona, que tiene un campo de tipo Lista . es decir:

Public class Person { List names; } 

Si lo llamo con una matriz de nombres, ¡todo funciona bien! p.ej:

 { "names" : [ "Jhon", "Doe" ] } 

Pero si la persona tiene solo un nombre, mi cliente crea un solo elemento de valor, por ejemplo:

 { "names" : "Jhon" } 

Cuando trato de llamar al servicio con un valor único, recibo una excepción:

 Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token 

Pregunta:

¿Cómo debo crear / configurar mi servicio web para poder deserializar el campo de matriz cuando se me envían como un elemento único?

Ya leí

Deserialización de Jackson – con ArrayList contenida

y

¿Cómo puedo personalizar la serialización de una lista de objetos JAXB a JSON?

Y esto que refiere la última respuesta:

El cliente de Jersey no puede deserializar los servicios json – excepción (no puede deserializar la instancia)

Jaxb json faltan corchetes para una matriz de elementos

Pero ninguno de esos arregla el problema.

¡Gracias de antemano!

Después de un largo día, y otro … después de leer muchos wikis y preguntas frecuentes, finalmente funciona.

Lo que hice:

  1. Usa Jackson
  2. Forzar el uso de los proveedores de Jackson
  3. Definir deserializador personalizado
  4. activar la bandera ACCEPT_SINGLE_VALUE_AS_ARRAY
  5. Reparar dependencias

La historia:

Estaba usando Jersey 1.13 que usa (creo) jaxb por defecto.

Lo cambié para usar Jackson

  com.sun.jersey.api.json.POJOMappingFeature true  

como se describe en:

https://stackoverflow.com/a/13895768/660990

Esto hizo que mi camiseta usara a Jackson, pero el problema sigue siendo; Jackson no puede deserializar la matriz todavía.

Forcé el uso de los proveedores de Jackson :

  com.sun.jersey.config.property.packages  your.project.packages; org.codehaus.jackson.jaxrs  

https://stackoverflow.com/a/3143214/660990

Fue un paso necesario, pero no fue suficiente. Es necesario activar el indicador ACCEPT_SINGLE_VALUE_AS_ARRAY .

 ObjectMapper objectMapper; objectMapper = new ObjectMapper().configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); 

Necesitaba definir deserializador personalizado

 public class MyResolver implements ContextResolver { @Override public ObjectMapper getContext(final Class objectType) { ... return objectMapper; } } 

para hacer eso:

Customizing-ObjectMapper

Después de hacer todo esto todavía no funcionó …

Después de un poco más de tiempo de búsqueda, encontré:

Jackson 2.0 con Jersey 1.12

Eso discute problemas de dependencias ..

Esto reveló mi problema, Jersey v1.13 viene con Jackson v1.9.2 Necesito Jackson v2.0

Eliminé la dependencia de jersey-json, porque incluía jackson 1.9.2:

  com.sun.jersey jersey-json  

Y dependencia declarada directamente para:

  com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider  

Referencia:

jackson-jaxrs-json-provider

Nota: este cambio elimina la capacidad de Jersey de usar Jaxb o tirar.

Fuera del tema , puede ser interesante para alguien:

Configure Jersey / Jackson para NO utilizar la anotación de campo @XmlElement para la denominación de campos JSON

Los ejemplos 5.10 y 5.11 de esta página explican su problema exacto. Puede configurar el generador de JSON para forzar matrices para listas de un solo elemento, como por JSONConfiguration.mapped().arrays("names").build() : JSONConfiguration.mapped().arrays("names").build() .

Me funcionó agregando @JsonSerialize a la clase

 @JsonSerialize Public class Person { List names; } 

Puede hacer esto con anotaciones a nivel de clase, campo o método utilizando la anotación JsonFormat

 @JsonFormat(with = Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) protected List list; public List getList() { return list; } public void setList(List list) { this.list = list; } 
 {"results": {"place": {"lang": "en-US","woeid": "2168606"}}} 

&

 {"results": {"place": [{"lang": "en-US","woeid": "2168606"}, {"lang": "en-US","woeid": "2168606"}]}} 

este tipo de cómo hacerlo … al usar yahoo place api