Использование Retrofit для доступа к массивам JSON
Я думал, что понял, как это сделать, но, очевидно, нет. У меня есть API от Flickr, который начинается следующим образом:
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"
}
Теперь мне нужно получить информацию из массива фотографий, поэтому я пытаюсь сделать это:
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;
}
}
Очень ясно, что, похоже, я пропущу точку, однако я не уверен, как получить информацию.
Ответы
Ответ 1
Быстрый взгляд на доработку документов говорит, что он использует Gson для преобразования классов JSON в Java. Это означает, что вам нужна иерархия классов в Java, которая соответствует JSON. Твой... не делает.
Возвращенный JSON - это объект с одним полем "фотографии", который содержит объект;
{ "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 соответствующим образом.
Ответ 2
Я бы предложил использовать http://www.jsonschema2pojo.org. Вы можете вставить свой JSON, и он будет генерировать POJO для вас.
Это должно сделать трюк.
Ответ 3
Принятый ответ правильный, но для этого требуется создать класс 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);
}
}
Теперь мы создаем наш пользовательский объект gson для Retrofit RestAdapter:
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);
Таким образом мы получаем объект Photos без создания класса PhotosResponse. Мы можем использовать его следующим образом:
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) {
}
});
Ответ 4
Вы должны иметь возможность напрямую обращаться к com.google.gson.JsonObject из Retrofit и получать доступ к любому полю, которое вы хотите.
Поэтому, если вас интересует только массив фотографий, то это должно работать:
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());
Конечно, все проверки на здравомыслие оставлены вам.
Ответ 5
Поскольку уже несколько ответов выше, вы можете использовать. Но, по моему мнению, используйте это.
Создайте класс фотографии со всеми переменными, заданными в объекте фотографий, и создайте сеттер для всех, а также создайте класс фотографии, в котором будет сохранен список фотографий, а также создайте сеттер-получатель этого списка в классе 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.
}