web-dev-qa-db-ja.com

Retrofitを使用してJSON配列にアクセスする

私はこれを行う方法を理解したと思ったが、明らかにそうではなかった。私はFlickrからAPIを入手しています。

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

今、私が取得する必要がある情報は写真配列内からのものなので、私がやろうとしていることは:

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

私はポイントを逃しているように見えますが、情報を取得する方法がわかりません。

37
K20GH

Retrofitのドキュメントを簡単に見ると、Gsonを使用してJSONをJavaクラスに変換しています。つまり、JSONに一致するJavaのクラス階層が必要です。 ...しません。

返されるJSONは、オブジェクトを保持する単一のフィールド「photos」を持つオブジェクトです。

{ "photos" : { ... } }

したがって、トップレベルのクラスは、単一のフィールドを持つJavaクラスになります。

public class PhotosResponse {
    private Photos photos;

    // getter/setter
}

そして、そのPhotosタイプは、フィールドに含まれるオブジェクトのJSONに一致する別のクラスになります。

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

だからあなたは持っているだろう:

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

    // getters / setters
}

そして、その内部配列のオブジェクトの構造に一致するPhotoクラスを作成します。 Gsonは、返されたJSONを適切にマッピングします。

42
Brian Roach

http://www.jsonschema2pojo.org を使用することをお勧めします。 JSONを貼り付けると、POJOが生成されます。

これでうまくいくはずです。

47
LaSombra

受け入れられた答えは正しいですが、その中に1つのオブジェクトのみを含むPhotoResponseクラスを構築する必要があります。これは次のソリューションです。Photosクラスといくつかの滅菌を作成するだけです。

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

    }

}

次に、レトロフィットのRestAdapterにカスタムgsonオブジェクトを作成します。

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

そして、変換アダプターにコンバーターを設定します。

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

そして、インターフェースは次のようになります。

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

このようにして、PhotosResponseクラスを作成せずにPhotosオブジェクトを取得します。次のように使用できます。

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

Retrofitからcom.google.gson.JsonObjectに直接アクセスし、任意のフィールドにアクセスできる必要があります。したがって、Photo配列のみに関心がある場合は、次のように機能します。

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

そして実際にサービスを呼び出すときは、JsonObjectを実行して必要なものを取得するだけです。

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

もちろん、すべての健全性チェックはあなたに任されています。

2
Gomino

すでにいくつかの答えが上にあるので、それ以上を使用できます。しかし、私の見解では、これを使用します。 photosオブジェクトで指定されたすべての変数を使用して写真クラスを作成し、すべてのゲッターセッターを作成し、写真のリストを保持する写真のクラスを作成し、Photosクラスの横にこのリストのゲッターセッターも作成します。以下にコードを示します。

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