292

This might be a dumb question but what is the simplest way to read and parse JSON from URL in Java?

In Groovy, it's a matter of few lines of code. Java examples that I find are ridiculously long (and have huge exception handling block).

All I want to do is to read the content of this link.

4
  • 10
    The exception handling is required as java forces you to handle any exceptions that are declared. What's wrong with exception handling?
    – Falmarri
    Commented Nov 29, 2010 at 22:08
  • 3
    well, the "java force you" is the biggest problem Commented Mar 6, 2015 at 18:54
  • 10
    If java didn't force you to handle exceptions do you think programs would still run and run well? What if I was asked to input my age into a program and I gave snarfleblagger as my input? Should java allow the program to just execute with no issues? If you don't want to handle exceptions then declare them as being thrown by the methods that they may occur in and watch your program fail when something isn't perfectly right.
    – Batman
    Commented Jul 11, 2015 at 20:37
  • 4
    Not a dumb question at all. Especially coming from PHP where you can do this with json_decode(file_get_contents($url)); and be done!
    – dtbarne
    Commented Jan 18, 2016 at 22:21

12 Answers 12

227

Using the Maven artifact org.json:json I got the following code, which I think is quite short. Not as short as possible, but still usable.

package so4308554;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;

import org.json.JSONException;
import org.json.JSONObject;

public class JsonReader {

  private static String readAll(Reader rd) throws IOException {
    StringBuilder sb = new StringBuilder();
    int cp;
    while ((cp = rd.read()) != -1) {
      sb.append((char) cp);
    }
    return sb.toString();
  }

  public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
    InputStream is = new URL(url).openStream();
    try {
      BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
      String jsonText = readAll(rd);
      JSONObject json = new JSONObject(jsonText);
      return json;
    } finally {
      is.close();
    }
  }

  public static void main(String[] args) throws IOException, JSONException {
    JSONObject json = readJsonFromUrl("https://graph.facebook.com/19292868552");
    System.out.println(json.toString());
    System.out.println(json.get("id"));
  }
}
9
  • 4
    instead of reading character by character you can use readLine() on BufferedReader. This will reduce the number of iterations of while loop.
    – kdabir
    Commented Dec 1, 2010 at 12:52
  • 8
    What for? The readLine function will do the loop then, and I have to concatenate the lines instead of the characters, which is more expensive. That wouldn't keep the code as short as it is now. Furthermore, in JSON notation there is no concept of "lines", so why should I read them as such? Commented Dec 1, 2010 at 23:20
  • 6
    Consider Apache commons-io's IOUtils.toString(InputStream) method. That should save you some lines and responsibility. Commented Dec 5, 2013 at 10:46
  • 4
    Why i am getting this error "The constructor JSONObject(String) is undefined" in the line of JSONObject json = new JSONObject(jsonText); in "readJsonFromUrl" method..? @RolandIllig Commented Nov 5, 2014 at 5:18
  • 2
    With GSON, Jackson, Boon, Genson and others, you only need to feed the source: either just URL, or at most InputStream. While code above may be short for org.json usage, make sure to verify other libs available -- there is no need to write more than 1-3 lines of code for this task.
    – StaxMan
    Commented Jun 1, 2015 at 23:20
74

Here are couple of alternatives versions with Jackson (since there are more than one ways you might want data as):

  ObjectMapper mapper = new ObjectMapper(); // just need one
  // Got a Java class that data maps to nicely? If so:
  FacebookGraph graph = mapper.readValue(url, FaceBookGraph.class);
  // Or: if no class (and don't need one), just map to Map.class:
  Map<String,Object> map = mapper.readValue(url, Map.class);

And specifically the usual (IMO) case where you want to deal with Java objects, can be made one liner:

FacebookGraph graph = new ObjectMapper().readValue(url, FaceBookGraph.class);

Other libs like Gson also support one-line methods; why many examples show much longer sections is odd. And even worse is that many examples use obsolete org.json library; it may have been the first thing around, but there are half a dozen better alternatives so there is very little reason to use it.

7
  • 1
    What is url here? Is it a string or URL object or byte[]?
    – Dinesh
    Commented Mar 1, 2015 at 5:45
  • 1
    I was thinking of java.net.URL but either one works, as well as plenty of other sources (File, InputStream, Reader, String).
    – StaxMan
    Commented Mar 3, 2015 at 0:42
  • 5
    It should be java.net.URL in the example above, otherwise it will try to parse string 'http://....' as a json, which will yield an error
    – zbstof
    Commented Dec 30, 2015 at 21:40
  • @Zotov Yes. Passing String would require contents to be JSON, and not textual encoding of URI/URL to use.
    – StaxMan
    Commented Jan 4, 2016 at 1:08
  • 3
    Unrecognized token 'https': was expecting ('true', 'false' or 'null')
    – 3xCh1_23
    Commented Mar 1, 2017 at 1:21
73

The easiest way: Use gson, google's own goto json library. https://code.google.com/p/google-gson/

Here is a sample. I'm going to this free geolocator website and parsing the json and displaying my zipcode. (just put this stuff in a main method to test it out)

    String sURL = "http://freegeoip.net/json/"; //just a string

    // Connect to the URL using java's native library
    URL url = new URL(sURL);
    URLConnection request = url.openConnection();
    request.connect();

    // Convert to a JSON object to print data
    JsonParser jp = new JsonParser(); //from gson
    JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
    JsonObject rootobj = root.getAsJsonObject(); //May be an array, may be an object. 
    String zipcode = rootobj.get("zip_code").getAsString(); //just grab the zipcode
8
  • 1
    Why i'm getting the 'NetworkOnMainThreadException' error? I must user an AsyncTask or there is another way? In this example did you get this error too?
    – Benetz
    Commented May 22, 2015 at 13:05
  • Typo, should be: rootobj.get("zip_code").getAsString();
    – loopasam
    Commented Jun 19, 2015 at 8:07
  • How do i import the jsonParser? I always get the error: 'Error:(69, 9) error: cannot find symbol class JsonParser'
    – MAESTRO_DE
    Commented Oct 11, 2016 at 16:10
  • 2
    Please add maven dependency <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.0</version> </dependency> to get the JsonParse in your pom file.
    – Bug
    Commented Jan 10, 2017 at 16:21
  • can be simplified and handled in a typesafe way with Gson like: MyResponseObject response = new GsonBuilder().create().fromJson(new InputStreamReader((InputStream) request.getContent()), MyResponseObject.class);
    – Gregor
    Commented Apr 19, 2019 at 10:11
56

If you don't mind using a couple libraries it can be done in a single line.

Include Apache Commons IOUtils & json.org libraries.

JSONObject json = new JSONObject(IOUtils.toString(new URL("https://graph.facebook.com/me"), Charset.forName("UTF-8")));

Maven dependency:

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.7</version>
</dependency>
5
  • 1
    @andrdoiddev - You should ask that as a separate question. It is more general to Apache Commons, Gradle and Android Development.
    – ezwrighter
    Commented Nov 17, 2017 at 19:44
  • 1
    This is quite old now, but is still a good solution, so just in case @andrdoiddev or anyone else still needs the Gradle dependencies, these are the ones I'm using: compile group: 'org.json', name: 'json', version: '20180813' compile group: 'commons-io', name: 'commons-io', version: '2.6'
    – r02
    Commented Sep 12, 2018 at 16:27
  • Say you are firing multiple requests, saving the json responses to a JSONArray and then writing the JSONArray to a file using FileWriter, then this library DOES NOT ESCAPE double quotes. This makes the file be easily parsed back to JSONArray.
    – Gh0sT
    Commented Mar 26, 2019 at 15:47
  • 1
    Thanks @Irregardless, looks like json.org re-worked their packages. There is no longer a default reference java implementation on their site. I will update the link to use the first java project in their list of java libraries on their home page json.org as that should work and be compatible as it's a reference implementation.
    – ezwrighter
    Commented Aug 4, 2020 at 18:16
  • retrieves a null exception, is not a solution Commented Sep 29, 2022 at 4:50
8

The Oracle Documentation describes how

  1. an HttpRequest is built and then
  2. sent by the HttpClient to the URL

in just a few lines of code, by using only the Java Class Library. Put this code into your main method:

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("http://example.com/"))
      .build();
client.sendAsync(request, BodyHandlers.ofString())
      .thenApply(HttpResponse::body)
      .thenAccept(System.out::println)
      .join();

The response consists of a JSON object { ... } and can be further processed in your application. Here I printed it to the console, just to confirm it works:

System.out.println(request);

This is available for Java Versions 11+

6

I have done the json parser in simplest way, here it is

package com.inzane.shoapp.activity;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class JSONParser {

static InputStream is = null;
static JSONObject jObj = null;
static String json = "";

// constructor
public JSONParser() {

}

public JSONObject getJSONFromUrl(String url) {

    // Making HTTP request
    try {
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "iso-8859-1"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
            System.out.println(line);
        }
        is.close();
        json = sb.toString();

    } catch (Exception e) {
        Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    // try parse the string to a JSON object
    try {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
        System.out.println("error on parse data in jsonparser.java");
    }

    // return JSON String
    return jObj;

}
}

this class returns the json object from the url

and when you want the json object you just call this class and the method in your Activity class

my code is here

String url = "your url";
JSONParser jsonParser = new JSONParser();
JSONObject object = jsonParser.getJSONFromUrl(url);
String content=object.getString("json key");

here the "json key" is denoted that the key in your json file

this is a simple json file example

{
    "json":"hi"
}

Here "json" is key and "hi" is value

This will get your json value to string content.

0
6

Use HttpClient to grab the contents of the URL. And then use the library from json.org to parse the JSON. I've used these two libraries on many projects and they have been robust and simple to use.

Other than that you can try using a Facebook API java library. I don't have any experience in this area, but there is a question on stack overflow related to using a Facebook API in java. You may want to look at RestFB as a good choice for a library to use.

0
5

I have found this to be the easiest way by far.

Use this method:

public static String getJSON(String url) {
        HttpsURLConnection con = null;
        try {
            URL u = new URL(url);
            con = (HttpsURLConnection) u.openConnection();

            con.connect();


            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line + "\n");
            }
            br.close();
            return sb.toString();


        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (con != null) {
                try {
                    con.disconnect();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
        return null;
    }

And use it like this:

String json = getJSON(url);
JSONObject obj;
   try {
         obj = new JSONObject(json);
         JSONArray results_arr = obj.getJSONArray("results");
         final int n = results_arr.length();
            for (int i = 0; i < n; ++i) {
                // get the place id of each object in JSON (Google Search API)
                String place_id = results_arr.getJSONObject(i).getString("place_id");
            }


   }
1
  • 1
    You have got a ClassCastException exception sitting in there. Change the line URL u = new URL(url); to this URL u = new URL(null, url, new sun.net.www.protocol.https.Handler()); for this code to work
    – sunny arya
    Commented May 2, 2020 at 7:04
4

It's very easy, using jersey-client, just include this maven dependency:

<dependency>
  <groupId>org.glassfish.jersey.core</groupId>
  <artifactId>jersey-client</artifactId>
  <version>2.25.1</version>
</dependency>

Then invoke it using this example:

String json = ClientBuilder.newClient().target("http://api.coindesk.com/v1/bpi/currentprice.json").request().accept(MediaType.APPLICATION_JSON).get(String.class);

Then use Google's Gson to parse the JSON:

Gson gson = new Gson();
Type gm = new TypeToken<CoinDeskMessage>() {}.getType();
CoinDeskMessage cdm = gson.fromJson(json, gm);
0
3

I wanted to add an updated answer here since (somewhat) recent updates to the JDK have made it a bit easier to read the contents of an HTTP URL. Like others have said, you'll still need to use a JSON library to do the parsing, since the JDK doesn't currently contain one. Here are a few of the most commonly used JSON libraries for Java:

To retrieve JSON from a URL, this seems to be the simplest way using strictly JDK classes (but probably not something you'd want to do for large payloads), Java 9 introduced: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html#readAllBytes()

try(java.io.InputStream is = new java.net.URL("https://graph.facebook.com/me").openStream()) {
    String contents = new String(is.readAllBytes());
}

To parse the JSON using the GSON library, for example

com.google.gson.JsonElement element = com.google.gson.JsonParser.parseString(contents); //from 'com.google.code.gson:gson:2.8.6'
1

I am not sure if this is efficient, but this is one of the possible ways:

Read json from url use url.openStream() and read contents into a string.

construct a JSON object with this string (more at json.org)

JSONObject(java.lang.String source)
      Construct a JSONObject from a source JSON text string.
1

Here's a full sample of how to parse Json content. The example takes the Android versions statistics (found from Android Studio source code here, which links to here).

Copy the "distributions.json" file you get from there into res/raw, as a fallback.

build.gradle

    implementation 'com.google.code.gson:gson:2.8.6'

manifest

  <uses-permission android:name="android.permission.INTERNET" />

MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (savedInstanceState != null)
            return
        thread {
            // https://cs.android.com/android/platform/superproject/+/studio-master-dev:tools/adt/idea/android/src/com/android/tools/idea/stats/DistributionService.java
            var root: JsonArray
            Log.d("AppLog", "loading...")
            try {
                HttpURLConnection.setFollowRedirects(true)
                val statsUrl = "https://dl.google.com/android/studio/metadata/distributions.json" //just a string
                val url = URL(statsUrl)
                val request: HttpURLConnection = url.openConnection() as HttpURLConnection
                request.connectTimeout = 3000
                request.connect()
                InputStreamReader(request.content as InputStream).use {
                    root = JsonParser.parseReader(it).asJsonArray
                }
            } catch (e: Exception) {
                Log.d("AppLog", "error while loading from Internet, so using fallback")
                e.printStackTrace()
                InputStreamReader(resources.openRawResource(R.raw.distributions)).use {
                    root = JsonParser.parseReader(it).asJsonArray
                }
            }
            val decimalFormat = DecimalFormat("0.00")
            Log.d("AppLog", "result:")

            root.forEach {
                val androidVersionInfo = it.asJsonObject
                val versionNickName = androidVersionInfo.get("name").asString
                val versionName = androidVersionInfo.get("version").asString
                val versionApiLevel = androidVersionInfo.get("apiLevel").asInt
                val marketSharePercentage = androidVersionInfo.get("distributionPercentage").asFloat * 100f
                Log.d("AppLog", "\"$versionNickName\" - $versionName - API$versionApiLevel - ${decimalFormat.format(marketSharePercentage)}%")
            }
        }
    }
}

As alternative to the dependency, you can also use this instead:

InputStreamReader(request.content as InputStream).use {
    val jsonArray = JSONArray(it.readText())
}

and the fallback:

InputStreamReader(resources.openRawResource(R.raw.distributions)).use {
    val jsonArray = JSONArray(it.readText())
}

The result of running this:

loading...
result:
"Ice Cream Sandwich" - 4.0 - API15 - 0.20%
"Jelly Bean" - 4.1 - API16 - 0.60%
"Jelly Bean" - 4.2 - API17 - 0.80%
"Jelly Bean" - 4.3 - API18 - 0.30%
"KitKat" - 4.4 - API19 - 4.00%
"Lollipop" - 5.0 - API21 - 1.80%
"Lollipop" - 5.1 - API22 - 7.40%
"Marshmallow" - 6.0 - API23 - 11.20%
"Nougat" - 7.0 - API24 - 7.50%
"Nougat" - 7.1 - API25 - 5.40%
"Oreo" - 8.0 - API26 - 7.30%
"Oreo" - 8.1 - API27 - 14.00%
"Pie" - 9.0 - API28 - 31.30%
"Android 10" - 10.0 - API29 - 8.20%

Not the answer you're looking for? Browse other questions tagged or ask your own question.