Usando Retrofit para acceder a las matrices JSON

Pensé que entendía cómo hacer esto, pero obviamente no. Tengo mi API de Flickr, que comienza así:

jsonFlickrApi({ "photos":{ "page":1, "pages":10, "perpage":100, "total":1000, "photo":[ { "id":"12567883725", "owner":"74574845@N05", "secret":"a7431762dd", "server":"7458", "farm":8, "title":"", "ispublic":1, "isfriend":0, "isfamily":0, "url_l":"http:\/\/farm8.staticflickr.com\/7458\/12567883725_a7431762dd_b.jpg", "height_l":"683", "width_l":"1024" } 

Ahora la información que necesito obtener es desde el conjunto de fotos, así que lo que he estado tratando de hacer es:

 interface ArtService { @GET("/services/rest/?method=flickr.photos.getRecent&extras=url_l&owner_name&format=json") PhotosResponse getPhotos(); public class PhotosResponse { Photos photos; } public class Photos { List photo; } public class Arraz { int id; String title; String owner; String url_l; } } 

Muy claro que parece que me estoy perdiendo el sentido, sin embargo, no estoy seguro de cómo obtener la información.

Una mirada rápida a los documentos de Retrofit dice que usa Gson para convertir clases JSON a Java. Esto significa que necesita una jerarquía de clases en Java que coincida con el JSON. El tuyo … no lo hace.

El JSON devuelto es un objeto con un solo campo “fotos” que contiene un objeto;

 { "photos" : { ... } } 

Por lo tanto, su clase de nivel superior sería una clase de Java con un solo campo:

 public class PhotosResponse { private Photos photos; // getter/setter } 

Y ese tipo de Photos sería otra clase que coincide con el JSON para el objeto que el campo contiene:

 { "page":1, "pages":10, ... } 

Entonces tendrías:

 public class Photos { private int page; private int pages; private int perpage' private int total; private List photo; // getters / setters } 

Y luego crearías una clase de Photo para que coincida con la estructura del objeto en esa matriz interna. Gson luego mapeará el JSON devuelto apropiadamente.

Sugeriría utilizar http://www.jsonschema2pojo.org . Puede pegar su JSON y generará los POJOs para usted.

Eso debería hacer el truco.

La respuesta aceptada es correcta, pero requiere la creación de una clase PhotoResponse que solo tenga un objeto. Esta es la siguiente solución, solo necesitamos crear la clase de fotos y algo de esterilización.

Creamos un JsonDeserializer:

 class PhotosDeserializer implements JsonDeserializer { @Override public Photos deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonElement content = json.getAsJsonObject().get("photos"); return new Gson().fromJson(content, Photos.class); } } 

Ahora creamos nuestro objeto gson personalizado para el RestAdapter de Retrofit:

  Gson gson = new GsonBuilder() .registerTypeAdapter(Photos.class, new PhotosDeserializer()) .create(); 

Y luego configuramos el convertidor en el adaptador de actualización:

  RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(ArtService.ENDPOINT) .setConverter(new GsonConverter(gson)) .build(); 

Y la interfaz se vería así:

 @GET("/?method="+METHOD_GET_RECENT+"&api_key="+API_KEY+"&format=json&nojsoncallback=1&extras="+EXTRAS_URL) public void getPhotos(Callback response); 

De esta manera obtenemos el objeto Photos sin tener que crear la clase PhotosResponse. Podemos usarlo así:

 ArtService artService = restAdapter.create(ArtService.class); artService.getPhotos(new Callback() { @Override public void success(Photos photos, Response response) { // Array of photos accessing by photos.photo } @Override public void failure(RetrofitError error) { } }); 

Debería poder acceder directamente a com.google.gson.JsonObject desde Retrofit y acceder al campo que desee. Entonces, si solo estás interesado en la matriz de fotos, algo como esto debería funcionar:

 interface ArtService { @GET("/services/rest/?method=flickr.photos.getRecent&extras=url_l&owner_name&format=json") JsonObject getPhotos(); public class Photo { int id; String title; String owner; String url_l; } } 

Y cuando realmente llame al servicio, simplemente ejecute JsonObject para obtener lo que desea:

  JsonObject json = mRestClient.getArtService().getPhotos(); List photos = new Gson().fromJson(json.getAsJsonObject("photos").get("photo").toString(), new TypeToken>() {}.getType()); 

Por supuesto, todos los controles de cordura se dejan a usted.

Como ya hay algunas respuestas arriba que puedes usar. Pero según mi punto de vista, use esto. Haga una clase de fotografía con todas las variables dadas en el objeto photos y cree un setter getter de todo y también cree una clase de foto con la que se mantendrá la lista de fotos y también crear setter getter de esta lista al lado de la clase Photos. Debajo está el código dado.

 public static class Photos { @JsonProperty("page") private double page; @JsonProperty("pages") private double pages; @JsonProperty("perpage") private double perpage; @JsonProperty("total") private double total; @JsonProperty("photo") private List photo; public double getPage() { return page; } public void setPage(double page) { this.page = page; } public double getPages() { return pages; } public void setPages(double pages) { this.pages = pages; } public double getPerpage() { return perpage; } public void setPerpage(double perpage) { this.perpage = perpage; } public double getTotal() { return total; } public void setTotal(double total) { this.total = total; } } public static class Photo { // refer first class and declare all variable of photo array and generate getter setter. }