How to extract Array from JSON into an object’s List type attribute

Asked

Viewed 1,947 times

4

I am using the Flickr API to get the information from the images, which returns the following JSON:

{"photos":{"page":1,"pages":60,"perpage":100,"total":"5964","photo":[{"id":"21577339501","Owner":"85277110@N02","secret":"31e850dfeb","server":"5785","farm":6,"title":"P1390956","ispublic":1,"isfriend":0,"isfamily":0}, {"id":"21577287101","Owner":"852710@N02","secret":"412990658f","server":"611","farm":1,"title":"P1400012","ispublic":1,"isfriend":0,"isfamily":0}, {continues the list of json objects}]

I do the following code in the Spring controller to rescue the objects:

Collection<Photos> readValues = objectMapper.readValue(new URL(url), new TypeReference<Collection<Photos>>() { });

And returns the following error:

com.fasterxml.Jackson.databind.Jsonmappingexception: Can not deserialize instance of java.util.Arraylist out of START_OBJECT token

I wonder how I can convert this list of objects from the attribute photo that is present in photos for a ArrayList. I have searched the internet for several solutions and so far found none.

Photos.class:

public class Photos {

    @JsonProperty("page")
    private Integer page;

    @JsonProperty("pages")
    private Integer pages;

    @JsonProperty("perpage")
    private Integer perpage;

    @JsonProperty("total")
    private Integer total;

    @JsonProperty("photo")
    @JsonDeserialize(contentAs = Photo.class, as = ArrayList.class)
    private List<Photo> photo;

    public Photos() {}

    public Photos(Integer page, Integer pages, Integer perpage, Integer total,
            List<Photo> photo) {
        super();
        this.page = page;
        this.pages = pages;
        this.perpage = perpage;
        this.total = total;
        this.photo = photo;
    }

    public Photos(List<Photo> photo) {
        super();
        this.photo = photo;
    }

    public Integer getPage() {
        return page;
    }
    public void setPage(Integer page) {
        this.page = page;
    }
    public Integer getPages() {
        return pages;
    }
    public void setPages(Integer pages) {
        this.pages = pages;
    }
    public Integer getPerpage() {
        return perpage;
    }
    public void setPerpage(Integer perpage) {
        this.perpage = perpage;
    }
    public Integer getTotal() {
        return total;
    }
    public void setTotal(Integer total) {
        this.total = total;
    }
    public List<Photo> getPhoto() {
        return photo;
    }

    public void setPhoto(List<Photo> photo) {
        this.photo = photo;
    }
}

Photo.class:

public class Photo {

    @JsonProperty("id")
    private Integer id;

    @JsonProperty("owner")
    private String owner;

    @JsonProperty("secret")
    private String secret;

    @JsonProperty("server")
    private Integer server;

    @JsonProperty("farm")
    private Integer farm;

    @JsonProperty("title")
    private String title;

    @JsonProperty("ispublic")
    private Boolean isPublic;

    @JsonProperty("isfriend")
    private Boolean isFriend;

    @JsonProperty("isfamily")
    private Boolean isFamily;

    public Photo() { }

    public Photo(Integer id, String owner, String secret, Integer server,
            Integer farm, String title, Boolean isPublic, Boolean isFriend,
            Boolean isFamily) {
        super();
        this.id = id;
        this.owner = owner;
        this.secret = secret;
        this.server = server;
        this.farm = farm;
        this.title = title;
        this.isPublic = isPublic;
        this.isFriend = isFriend;
        this.isFamily = isFamily;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getOwner() {
        return owner;
    }
    public void setOwner(String owner) {
        this.owner = owner;
    }
    public String getSecret() {
        return secret;
    }
    public void setSecret(String secret) {
        this.secret = secret;
    }
    public Integer getServer() {
        return server;
    }
    public void setServer(Integer server) {
        this.server = server;
    }
    public Integer getFarm() {
        return farm;
    }
    public void setFarm(Integer farm) {
        this.farm = farm;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public Boolean getIsPublic() {
        return isPublic;
    }
    public void setIsPublic(Boolean isPublic) {
        this.isPublic = isPublic;
    }
    public Boolean getIsFriend() {
        return isFriend;
    }
    public void setIsFriend(Boolean isFriend) {
        this.isFriend = isFriend;
    }
    public Boolean getIsFamily() {
        return isFamily;
    }
    public void setIsFamily(Boolean isFamily) {
        this.isFamily = isFamily;
    }

}

1 answer

3


There are several ways to deserialize this your object using Jackson, I will cite only two of them, then you can choose the one you think most appropriate to use in your context.

First, considering the JSON that reported, apparently what you have is a wrong mapping. In this excerpt:

Collection<Photos> readValues = objectMapper.readValue(new URL(url), new TypeReference<Collection<Photos>>() { });

You try to directly obtain a collection of Photos, but according to JSON you don’t have a collection of them, but a random object, which has an object Photos that only then will have the list of objects of type Photo.

So again considering this JSON:

{
   "photos":{
      "page":1,
      "pages":60,
      "perpage":100,
      "total":"5964",
      "photo":[
         {
            "id":"21577339501",
            "owner":"85277110@N02",
            "secret":"31e850dfeb",
            "server":"5785",
            "farm":6,
            "title":"P1390956",
            "ispublic":1,
            "isfriend":0,
            "isfamily":0
         },
         {
            "id":"21577287101",
            "owner":"85277110@N02",
            "secret":"412990658f",
            "server":"611",
            "farm":1,
            "title":"P1400012",
            "ispublic":1,
            "isfriend":0,
            "isfamily":0
         }
      ]
   }
}

To recover the list of photo, Let’s deserialize for some object, called OutsideObject, containing an object of the type Photos and after it retrieves the list. The entities were like this:

  • OutsideObject:

public class OutsideObject {

    private Photos photos;

    // getter e setter

}
  • Photos:

public class Photos {

    private Integer page;
    private Integer pages;
    private Integer perpage;
    private Integer total;
    private List<Photo> photo;

    // getters e setters

}
  • Photo:

public class Photo {

    private Long id;
    private String owner;
    private String secret;
    private Integer server;
    private Integer farm;
    private String title;

    @JsonProperty("ispublic")
    private Boolean isPublic;

    @JsonProperty("isfriend")
    private Boolean isFriend;

    @JsonProperty("isfamily")
    private Boolean isFamily;

    // getters e setters

}

And the process of deserialization was like this:

final ObjectMapper objectMapper = new ObjectMapper();

final OutsideObject outsideObject = objectMapper.readValue(json, OutsideObject.class);
final Photos photos = outsideObject.getPhotos();
final List<Photo> photoList = photos.getPhoto();
// faça o que quiser com photoList

If you do not want to create this "auxiliary" object another way is by using the streaming API, in this case we will get the nodes until we get the list of Photo, will be something like this:

final JsonFactory factory = new JsonFactory();
final JsonParser parser = factory.createParser(json);

// avança o stream até chegar no array
while (parser.nextToken() != JsonToken.START_ARRAY) {
    parser.nextToken();
}

final ObjectMapper objectMapper = new ObjectMapper();

final List<Photo> photoList = objectMapper.readValue(parser, new TypeReference<List<Photo>>() {});
// faça o que quiser com photoList

Finally, if you want to recover the list directly, you can also create a deserialize customized.

  • Thank you very much for your reply, I will try here, I observed this photosand I thought with @JsonRootName would solve, the idea was even to create an object containing already the list of photos.

  • @Giancarlogiulian OK, anything just let me know that if I need to update my response

  • 1

    Thank you very much, it worked here, only with the instance of OutsideObject you can already manipulate the information quietly. + 1 and better answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.