web-dev-qa-db-de.com

Verwenden von Retrofit für den Zugriff auf JSON-Arrays

Ich dachte, ich verstehe, wie man das macht, aber offensichtlich nicht. Ich habe meine API von Flickr, die so beginnt:

jsonFlickrApi({
   "photos":{
      "page":1,
      "pages":10,
      "perpage":100,
      "total":1000,
      "photo":[
         {
            "id":"12567883725",
            "owner":"[email protected]",
            "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"
         }

Nun, die Informationen, die ich erhalten muss, stammen aus dem Fotoarray.

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

    public class Arraz {
        int id;
        String title;
        String owner;
        String url_l;
    }
}

Sehr klar, dass mir der Punkt zu fehlen scheint, aber ich bin nicht sicher, wie ich die Informationen bekomme.

37
K20GH

Ein kurzer Blick auf die Dokumente von Retrofit besagt, dass Json mit Gson in Java-Klassen konvertiert wird. Dies bedeutet, dass Sie in Java eine Klassenhierarchie benötigen, die zu JSON passt. Dein ... nicht.

Die zurückgegebene JSON ist ein Objekt mit einem einzelnen Feld "photos", das ein Objekt enthält.

{ "photos" : { ... } }

Ihre oberste Klasse-Klasse wäre also eine Java-Klasse mit einem einzelnen Feld:

public class PhotosResponse {
    private Photos photos;

    // getter/setter
}

Dieser Photos-Typ wäre eine andere Klasse, die mit der JSON für das in diesem Feld enthaltene Objekt übereinstimmt:

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

Du hättest also:

public class Photos {
    private int page;
    private int pages;
    private int perpage'
    private int total;
    private List<Photo> photo;

    // getters / setters
}

Und dann würden Sie eine Photo-Klasse erstellen, die der Struktur des Objekts in diesem inneren Array entspricht. Gson ordnet dann das zurückgegebene JSON entsprechend zu.

42
Brian Roach

Ich würde vorschlagen, http://www.jsonschema2pojo.org zu verwenden. Sie können Ihre JSON einfügen und die POJOs werden für Sie generiert.

Das sollte den Trick tun.

47
LaSombra

Die akzeptierte Antwort ist korrekt, es muss jedoch eine PhotoResponse-Klasse erstellt werden, die nur ein Objekt enthält. Bei dieser folgenden Lösung müssen wir nur die Photos-Klasse erstellen und einige Sterilisationen durchführen.

Wir erstellen einen JsonDeserializer:

class PhotosDeserializer implements JsonDeserializer<Photos>
{
    @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);

    }

}

Jetzt erstellen wir unser benutzerdefiniertes gson-Objekt für RestAdapter von Retrofit:

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

Und dann setzen wir den Konverter im Retrofit-Adapter:

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

Und das Interface würde so aussehen:

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

Auf diese Weise erhalten wir das Photos-Objekt, ohne die PhotosResponse-Klasse erstellen zu müssen. Wir können es so verwenden:

ArtService artService = restAdapter.create(ArtService.class);
artService.getPhotos(new Callback<Photos>() {
    @Override
    public void success(Photos photos, Response response) {

        // Array of photos accessing by photos.photo

   }

   @Override
   public void failure(RetrofitError error) {


    }
});
10
FOMDeveloper

Sie sollten in der Lage sein, direkt von Retrofit auf das com.google.gson.JsonObject zuzugreifen und auf das gewünschte Feld zuzugreifen. Wenn Sie sich nur für das Photo-Array interessieren, sollte Folgendes funktionieren:

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

Wenn Sie den Dienst tatsächlich anrufen, führen Sie einfach das JsonObject aus, um das zu erhalten, was Sie möchten:

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

Natürlich bleibt Ihnen die gesamte Überprüfung des Gesundheitszustandes vorbehalten.

2
Gomino

Da stehen schon wenige Antworten darüber, die du verwenden kannst. Aber meiner Meinung nach verwenden Sie dies. Erstellen Sie eine Fotoklasse mit allen in photos angegebenen Variablen, erstellen Sie einen Getter-Setter von allen und erstellen Sie auch eine Fotoklasse mit der Liste der Fotos. Außerdem können Sie einen Getter-Setter dieser Liste neben der Photos-Klasse erstellen. Unten ist der Code angegeben. 

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> 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.
    }
0
Vid