How to extract JSON Array into an object's List attribute of an object

4

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

  per page ": 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" "isfamily": 0}, {continues the objects in the json list}]

I make 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 would like to know how to convert this list of objects from the photo attribute that is present in photos to a ArrayList . I have already searched the internet for various solutions and so far I have not found any.

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

}
    
asked by anonymous 12.10.2015 / 01:32

1 answer

3

There are several ways to deserialize this object using Jackson, I'll cite just two of them, so you can choose the one that suits you best in context.

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

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

You try to get a collection of Photos directly, but according to JSON you do not have a collection of them, but an object that has a Photos object, which only has the list of objects of type Photo .

Then, 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 retrieve the list of photo , let's deserialize to any object, called OutsideObject , which contains an object of type Photos and after it retrieves the list. The entities look 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 deserialization process looks 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 "helper" objects another way is using the streaming API , in this case we will get the nodes until we get the list of Photo , it will look 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 directly retrieve the list, you can also create a deserialize custom .

    
12.10.2015 / 02:45