2012-05-26 19 views
7

Estoy analizando la respuesta de last.fm API. Pero parece que usaron alguna envoltura para algunas de las respuestas, lo que está causando un poco de dolor. Para poner un ejemplo:Jackson handling Elementos envueltos

{ 
    "artists":{ 
     "artist":[ 
     { 
      "name":"Coldplay", 
      "playcount":"816763", 
      "listeners":"120815", 
      "mbid":"cc197bad-dc9c-440d-a5b5-d52ba2e14234", 
      "url":"http:\/\/www.last.fm\/music\/Coldplay", 
      "streamable":"1" 
     }, 
     { 
      "name":"Radiohead", 
      "playcount":"846668", 
      "listeners":"99135", 
      "mbid":"a74b1b7f-71a5-4011-9441-d0b5e4122711", 
      "url":"http:\/\/www.last.fm\/music\/Radiohead", 
      "streamable":"1" 
     } 
     ], 
     "@attr":{ 
     "page":"1", 
     "perPage":"2", 
     "totalPages":"500", 
     "total":"1000" 
     } 
    } 
} 

No sólo la respuesta está envuelto en los artistas oponerse, pero la matriz de objeto tiene también una envoltura objeto.

Así como una clase contenedora:

public class LastFMArtistWrapper { 
    public List<Artist> artists; 

} 

no funcionaría. Trabajé alrededor de esto, creando dos clases de contenedor, pero esto se ve realmente feo. ¿Hay alguna manera de que podamos usar algo como @XMLElementWrapper en Jackson?

+0

Una de las ventajas de esta configuración es que es extensible. Si agregan más propiedades a la respuesta JSON, puede agregarlas fácilmente a sus objetos. Sin embargo, si lo manipula, es posible que deba deshacerlo más adelante si el JSON cambia nuevamente. Puede valer la pena mantener las cosas como están. Esa es solo mi sugerencia. Buena suerte encontrando una respuesta. +1 para la pregunta. – jmort253

Respuesta

5

La respuesta JSON que recibe del proveedor es una representación serializada de una jerarquía de objetos diferentes, pero de su descripción, parece que realmente solo necesita usar y trabajar con un subconjunto específico de esta representación, el colección de artistas.

Una solución para duplicar esta representación implica crear la misma jerarquía de clases de Java, lo que genera una sobrecarga adicional en forma de clases innecesarias. Por lo que entiendo, esto es lo que deseas evitar.

El proyecto org.json creó una clase genérica JSONObject, que representa un único par clave/valor genérico en una representación JSON más grande. Un JSONObject puede contener otros JSONObjects y JSONArrays, reflejando la representación sin la sobrecarga adicional de mantener y escribir clases adicionales.

Por lo tanto, estos dos objetos se pueden reutilizar en varias capas de jerarquía en una representación JSON, sin que sea necesario que replique la estructura. Aquí está un ejemplo de cómo se puede proceder:

// jsonText is the string representation of your JSON 
JSONObject jsonObjectWrapper = new JSONObject(jsonText); 

// get the "artists" object 
JSONObject jsonArtists = jsonObjectWrapper.get("artists"); 

// get the array and pass it to Jackson's ObjectMapper, using TypeReference 
    // to deserialize the JSON ArrayList to a Java ArrayList. 
List<Artist> artists = objectMapper.readValue(
     jsonObjectWrapper.getString("artist"), 
      new TypeReference<ArrayList<Artist>>() { }); 

Utilizando el método anterior, se corta el exceso de carga de tener que escribir capas adicionales de objetos POJO que no hacen sino añadir el desorden innecesario.

TestCollectionDeserialization contiene algunos ejemplos del método readValue al trabajar con colecciones y puede ser útil.

+0

¿no hay ninguna función de la biblioteca de jackson para encargarse de esto? una función Wrapper Ignor sería agradable – jiduvah

+0

@jiduvah - ¡Sería bueno! Lo he buscado, y siempre he llegado a la conclusión de que, a menos que necesite ese nivel de granularidad, es más fácil simplemente usar los objetos JSONObject y JSONArray. Si alguien creó un contenedor que tal vez solo usara metadatos para serializar y deserializar en lugar de requerir objetos reales, ¡eso sería increíble! – jmort253