Reputation: 151
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") + " " );
}
}
Upvotes: 2
Views: 5571
Reputation: 38655
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:
Upvotes: 2