1. Introduction

In this quick tutorial, we’re going to create methods able to read JSON data from any URL. We’ll start with core Java classes. Then, we’ll use a few libraries to make our code simpler.

2. Using Core Java Classes

One of the simplest ways to read data from a URL in Java is using the URL class. To use it, we open an input stream to a URL, create an input stream reader, then read all characters. We’ll append these characters to a StringBuilder and then return it as a String:

public static String stream(URL url) {
    try (InputStream input = url.openStream()) {
        InputStreamReader isr = new InputStreamReader(input);
        BufferedReader reader = new BufferedReader(isr);
        StringBuilder json = new StringBuilder();
        int c;
        while ((c = reader.read()) != -1) {
            json.append((char) c);
        }
        return json.toString();
    }
}

Consequently, the code includes a lot of boilerplate. Moreover, it would also require even more code if we wanted to convert our JSON into a map or a POJO. Even using the new Java 11 HttpClient, it’s a lot of code for a simple GET request. Also, it doesn’t help with converting the response from strings to POJO. So, let’s explore simpler ways to do this.

3. Using commons-io and org.json

A very popular library is Apache Commons IO. We’ll use IOUtils to read a URL and get a String back. Then, to convert it to a JSONObject, we’ll use the JSON-Java (org.json) library. This is a reference implementation for Java from json.org. Let’s combine them in a new method:

public static JSONObject getJson(URL url) {
    String json = IOUtils.toString(url, Charset.forName("UTF-8"));
    return new JSONObject(json);
}

With JSONObject, we can call get() for any properties and get an Object. There are similarly named methods for specific types. For example:

jsonObject.getString("stringProperty");

4. Less Code With Jackson and the ObjectMapper

There are many solutions for converting JSON into POJO and vice-versa. But, Jackson is widely used in projects like Jersey and other JAX-RS implementations. Let’s add the dependency we need to our pom.xml:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

With this, not only can we effortlessly read JSON from a URL, but we can also convert it to a POJO at the same time.

4.1. Deserializing to a Generic Object

Most of the action in Jackson comes from the ObjectMapper. The most common scenario for ObjectMapper is to give it a String input and get an object back. Luckily, ObjectMapper can also read input straight from an internet URL:

public static JsonNode get(URL url) {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.readTree(url);
}

With readTree(), we get a JsonNode, which is a tree-like structure. We read properties with its get() method:

json.get("propertyName");

Therefore, we don’t need to map our response to a specific class if we don’t want to.

4.2. Deserializing to a Custom Class

But, for more complex objects, it’s helpful to create a class that represents the JSON structure we expect. We can use generics to create a version of our method capable of mapping the response to any class we want with readValue():

public static <T> T get(URL url, Class<T> type) {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.readValue(url, type);
}

Then, as long as our object’s properties and structure match, we’ll get a new instance filled with values from the JSON response.

5. Conclusion

In this article, we learned how to make requests to a URL and get a JSON string back. Then, we used a few libraries to simplify our code. In the end, we read a JSON response while mapping it to a POJO in a couple of lines.

And as always, the source code is available over on GitHub.