Best way to access nested JSON objects with Java

Deane Kane :

I am new to working with JSON and I am wondering if there is a better way to accomplish what I am doing in the below code. You will notice to access a nested JSON object I am having to create child JSON Objects/Arrays before I can get to the JSON array element "leagues". Is there a faster or easier way to do this?

public static void main( String[] args ) throws UnirestException
{
    JsonNode response = Unirest.get("http://www.api-football.com/demo/api/v2/leagues")
            .header("x-rapidapi-host", "api-football-v1.p.rapidapi.com")
            .header("x-rapidapi-key", "")
            .asJson()
            .getBody();

    JSONObject json = new JSONObject( response );
    JSONArray jArray = json.getJSONArray( "array" );
    JSONObject jAPI = jArray.getJSONObject(0);
    JSONObject jLeagues = jAPI.getJSONObject( "api" );
    JSONArray jArrayLeagues = jLeagues.getJSONArray( "leagues" );

    for(int n = 0; n < jArrayLeagues.length(); n++) {
        JSONObject leagues = jArrayLeagues.getJSONObject(n);
        System.out.print(leagues.getString("name") + " " );
        System.out.print(leagues.getString("country") + " ");
        System.out.println( leagues.getInt("league_id") + " " );
    }
}

Link to the JSON data

Michał Ziober :

You can deserialise JSON payload to POJO classes using Gson or Jackson. Also, these two libraries can deserialise JSON to Java Collection - JSON Objects to Map and JSON Array to List, Set, array (T[]) or any other collection. Using jsonschema2pojo you can generate POJO classes for given JSON payload already with Gson or Jackson annotations.

When you do not need to process the whole JSON payload you can preprocess it using JsonPath library. For example, if you want to return only league names you can use $..leagues[*].name path. You can try it out using online tool and provide your JSON and path.

Your problem can be easily solved using Jackson as below:

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URL;
import java.util.List;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        // workaround for SSL not related with a question
        SSLUtilities.trustAllHostnames();
        SSLUtilities.trustAllHttpsCertificates();

        String url = "https://www.api-football.com/demo/api/v2/leagues";

        ObjectMapper mapper = new ObjectMapper()
                // ignore JSON properties which are not mapped to POJO
                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        // we do not want to build model for whole JSON payload
        JsonNode node = mapper.readTree(new URL(url));

        // go to leagues JSON Array
        JsonNode leaguesNode = node.at(JsonPointer.compile("/api/leagues"));

        // deserialise "leagues" JSON Array to List of POJO
        List<League> leagues = mapper.convertValue(leaguesNode, new TypeReference<List<League>>(){});
        leagues.forEach(System.out::println);
    }
}

class League {
    @JsonProperty("league_id")
    private int id;
    private String name;
    private String country;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    @Override
    public String toString() {
        return "League{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", country='" + country + '\'' +
                '}';
    }
}

Above code prints:

League{id=2, name='Premier League', country='England'}
League{id=6, name='Serie A', country='Brazil'}
League{id=10, name='Eredivisie', country='Netherlands'}
League{id=132, name='Champions League', country='World'}

See also:

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=165757&siteId=1