Search code examples
arraysjsonjacksonmappingresttemplate

Parse JSON array with resttemplate


I think I have a very common problem but I cant find a solution :(

I am using spring with restTemplate to recover a JSON object like this:

ResponseEntity<Download_urls> result= restTemplate.exchange(URL, HttpMethod.GET, entity, Download_urls.class);

Where "Download_urls " class have a JSON array inside:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)

public class Download_urls {    

    private Video[] video;

}

And Video.class

@JsonIgnoreProperties(ignoreUnknown = true)
public class Video {

    private String type;
    private String label;
    private String file;

    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getLabel() {
        return label;
    }
    public void setLabel(String label) {
        this.label = label;
    }
    public String getFile() {
        return file;
    }
    public void setFile(String file) {
        this.file = file;
    }

}

Obviously Video[] doesn't work to map JSON array. Any help?

Thanks

UPDATE: Example JSON payload:

{
    "id": 737132,
    "asset": {
        "_class": "asset",
        "id": 538362,
        "download_urls": {
            "Video": [{
                "type": "video/mp4",
                "label": "360"
            }, {
                "type": "video/mp4",
                "label": "720"
            }]
        }
    }
}

Solution

  • Your Java class names and its properties should follow Java naming conventions. Then your code is much more readable and nicer. And to convert JSON field names to and fro you can use naming strategies, e.g.: LowerCaseWithUnderscoresStrategy, PascalCaseStrategy, etc.

    Here you are how I thing classes should look like:

    Video.java - same as yours.

    DownloadUrls.java:

    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import com.fasterxml.jackson.databind.PropertyNamingStrategy.PascalCaseStrategy;
    import com.fasterxml.jackson.databind.annotation.JsonNaming;
    
    @JsonIgnoreProperties(ignoreUnknown = true)
    
    // PascalCaseStrategy is used here because of "Video" JSON field. I would expect
    // it to be called "video".
    @JsonNaming(PascalCaseStrategy.class)
    public class DownloadUrls {
    
        private Video[] video;
    
        public Video[] getVideo() {
            return video;
        }
        public void setVideo(Video[] video) {
            this.video = video;
        }
    }
    

    Asset.java:

    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import com.fasterxml.jackson.databind.PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy;
    import com.fasterxml.jackson.databind.annotation.JsonNaming;
    
    @JsonIgnoreProperties(ignoreUnknown = true)
    
    // LowerCaseWithUnderscoresStrategy is common strategy when used with JSON, but
    // in this case it is used because of "download_url" JSON field only.
    @JsonNaming(LowerCaseWithUnderscoresStrategy.class)
    public class Asset {
    
        int id;
        DownloadUrls downloadUrls;
    
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
    
        public DownloadUrls getDownloadUrls() {
            return downloadUrls;
        }
        public void setDownloadUrls(DownloadUrls downloadUrls) {
            this.downloadUrls = downloadUrls;
        }   
    }
    

    and outer type just for completeness sake:

    public class OuterType {
    
        int id;
        Asset asset;
    
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
    
        public Asset getAsset() {
            return asset;
        }
        public void setAsset(Asset asset) {
            this.asset = asset;
        }
    }
    

    Michal