Course – LS (cat=JSON/Jackson)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

JSON (JavaScript Object Notation) is a lightweight data-interchange format, and we most commonly use it for client-server communication. It’s both easy to read/write and language-independent. A JSON value can be another JSON object, array, number, string, boolean (true/false) or null.

In this tutorial, we’ll see how to create, manipulate and parse JSON using one of the available JSON processing libraries — JSON-Java library, also known as org.json.

Further reading:

Iterating Over an Instance of org.json.JSONObject

Learn how to iterate and traverse through a JSONObject

Escape JSON String in Java

Learn ways to escape a JSON String core Java or a library

2. Prerequisite

We’ll first need to add the following dependency in our pom.xml:

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20240303</version>
</dependency>

The latest version can be found in the Maven Central Repository.

Note that this package has already been included in Android SDK, so we shouldn’t include it while using the same.

3. JSON in Java [package org.json]

The JSON-Java library also known as org.json (not to be confused with Google’s org.json.simple) provides us with classes that are used to parse and manipulate JSON in Java.

Furthermore, this library can also convert between JSON, XML, HTTP Headers, Cookies, Comma Delimited List or Text, etc.

In this tutorial, we’ll have a look at the following classes:

  1. JSONObject – similar to Java’s native Map-like object, which stores unordered key-value pairs
  2. JSONArray – an ordered sequence of values similar to Java’s native Vector implementation
  3. JSONTokener – a tool that breaks a piece of text into a series of tokens that can be used by JSONObject or JSONArray to parse JSON strings
  4. CDL – a tool that provides methods to convert comma delimited text into a JSONArray and vice versa
  5. Cookie – converts from JSON String to cookies and vice versa
  6. HTTP – used to convert from JSON String to HTTP headers and vice versa
  7. JSONException – a standard exception thrown by this library

4. JSONObject

A JSONObject is an unordered collection of key and value pairs, resembling Java’s native Map implementations.

  • Keys are unique Strings that cannot be null.
  • Values can be anything from a Boolean, Number, String, or JSONArray to even a JSONObject.NULL object.
  • A JSONObject can be represented by a String enclosed within curly braces with keys and values separated by a colon, and pairs separated by a comma.
  • It has several constructors with which to construct a JSONObject.

It also supports the following main methods:

  1. get(String key) – gets the object associated with the supplied key, throws JSONException if the key is not found
  2. opt(String key) – gets the object associated with the supplied key, null otherwise
  3. put(String key, Object value) – inserts or replaces a key-value pair in current JSONObject.

The put() method is an overloaded method that accepts a key of type String and multiple types for the value.

For the complete list of methods supported by JSONObject, visit the official documentation.

Let’s now discuss some of the main operations supported by this class.

4.1. Creating JSON Directly From JSONObject

JSONObject exposes an API similar to Java’s Map interface.

We can use the put() method and supply the key and value as an argument:

JSONObject jo = new JSONObject();
jo.put("name", "jon doe");
jo.put("age", "22");
jo.put("city", "chicago");

Now our JSONObject would look like this:

{"city":"chicago","name":"jon doe","age":"22"}

There are seven different overloaded signatures of JSONObject.put() method. While the key can only be unique, non-null String, the value can be anything.

4.2. Creating JSON From Map

Instead of directly putting key and values in a JSONObject, we can construct a custom Map and then pass it as an argument to JSONObject‘s constructor.

This example will produce same results as above:

Map<String, String> map = new HashMap<>();
map.put("name", "jon doe");
map.put("age", "22");
map.put("city", "chicago");
JSONObject jo = new JSONObject(map);

4.3. Creating JSONObject From JSON String

To parse a JSON String to a JSONObject, we can just pass the String to the constructor.

This example will produce same results as above:

JSONObject jo = new JSONObject(
  "{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}"
);

The passed String argument must be a valid JSON; otherwise, this constructor may throw a JSONException.

4.4. Serialize Java Object to JSON

One of JSONObject’s constructors takes a POJO as its argument. In the example below, the package uses the getters from the DemoBean class and creates an appropriate JSONObject for the same.

To get a JSONObject from a Java Object, we’ll have to use a class that is a valid Java Bean:

DemoBean demo = new DemoBean();
demo.setId(1);
demo.setName("lorem ipsum");
demo.setActive(true);

JSONObject jo = new JSONObject(demo);

And here’s the JSONObject jo:

{"name":"lorem ipsum","active":true,"id":1}

Although we have a way to serialize a Java object to JSON string, there is no way to convert it back using this library. If we want that kind of flexibility, we can switch to other libraries such as Jackson.

5. JSONArray

A JSONArray is an ordered collection of values, resembling Java’s native Vector implementation.

  • Values can be anything from a Number, String, Boolean, JSONArray, or JSONObject to even a JSONObject.NULL object.
  • It’s represented by a String wrapped within square brackets and consists of a collection of values separated by commas.
  • Like JSONObject, it has a constructor that accepts a source String and parses it to construct a JSONArray.

These are the primary methods of the JSONArray class:

  1. get(int index) – returns the value at the specified index (between 0 and total length – 1), otherwise throws a JSONException
  2. opt(int index) – returns the value associated with an index (between 0 and total length – 1). If there’s no value at that index, then a null is returned.
  3. put(Object value) – append an object value to this JSONArray. This method is overloaded and supports a wide range of data types.

For a complete list of methods supported by JSONArray, visit the official documentation.

5.1. Creating JSONArray

Once we’ve initialized a JSONArray object, we can simply add and retrieve elements using the put() and get() methods:

JSONArray ja = new JSONArray();
ja.put(Boolean.TRUE);
ja.put("lorem ipsum");

JSONObject jo = new JSONObject();
jo.put("name", "jon doe");
jo.put("age", "22");
jo.put("city", "chicago");

ja.put(jo);

Following are the contents of our JSONArray (code is formatted for clarity):

[
    true,
    "lorem ipsum",
    {
        "city": "chicago",
        "name": "jon doe",
        "age": "22"
    }
]

5.2. Creating JSONArray Directly From JSON String

Like JSONObject, the JSONArray also has a constructor that creates a Java object directly from a JSON String:

JSONArray ja = new JSONArray("[true, \"lorem ipsum\", 215]");

This constructor may throw a JSONException if the source String isn’t a valid JSON String.

5.3. Creating JSONArray Directly From a Collection or an Array

The constructor of JSONArray also supports collection and array objects as arguments.

We simply pass them as an argument to the constructor, and it will return a JSONArray object:

List<String> list = new ArrayList<>();
list.add("California");
list.add("Texas");
list.add("Hawaii");
list.add("Alaska");

JSONArray ja = new JSONArray(list);

Now our JSONArray consists of the following:

["California","Texas","Hawaii","Alaska"]

6. JSONTokener

A JSONTokener takes a source String as input to its constructor and extracts characters and tokens from it. It’s used internally by classes of this package (like JSONObject, JSONArray) to parse JSON Strings.

There may not be many situations where we’ll directly use this class since we can achieve the same functionality using other simpler methods (like string.toCharArray()):

JSONTokener jt = new JSONTokener("lorem");

while(jt.more()) {
    Log.info(jt.next());
}

Now we can access a JSONTokener like an iterator, using the more() method to check if there are any remaining elements and next() to access the next element.

Here are the tokens received from the previous example:

l
o
r
e
m

7. CDL

We’re provided with a CDL (Comma Delimited List) class to convert comma delimited text into a JSONArray and vice versa.

7.1. Producing JSONArray Directly From Comma Delimited Text

In order to produce a JSONArray directly from the comma delimited text, we can use the static method rowToJSONArray(), which accepts a JSONTokener:

JSONArray ja = CDL.rowToJSONArray(new JSONTokener("England, USA, Canada"));

Here’s what our JSONArray consists of now:

["England","USA","Canada"]

7.2. Producing Comma Delimited Text From JSONArray

Let’s see how to reverse of the previous step and get back the comma delimited text from JSONArray:

JSONArray ja = new JSONArray("[\"England\",\"USA\",\"Canada\"]");
String cdt = CDL.rowToString(ja);

The String cdt now contains the following:

England,USA,Canada

7.3. Producing JSONArray of JSONObjects Using Comma Delimited Text

To produce a JSONArray of JSONObjects, we’ll use a text String containing both headers and data separated by commas.

We separate the different lines using a carriage return (\r) or line feed (\n).

The first line is interpreted as a list of headers, and all the subsequent lines are treated as data:

String string = "name, city, age \n" +
  "john, chicago, 22 \n" +
  "gary, florida, 35 \n" +
  "sal, vegas, 18";

JSONArray result = CDL.toJSONArray(string);

The object JSONArray result now consists of the following (output formatted for the sake of clarity):

[
    {
        "name": "john",
        "city": "chicago",
        "age": "22"
    },
    {
        "name": "gary",
        "city": "florida",
        "age": "35"
    },
    {
        "name": "sal",
        "city": "vegas",
        "age": "18"
    }
]

Notice that both data and header were supplied within the same String. We have an alternative way of doing this where we can achieve the same functionality by supplying a JSONArray to get the headers and a comma delimited String working as the data.

Again, we separate different lines using a carriage return (\r) or line feed (\n):

JSONArray ja = new JSONArray();
ja.put("name");
ja.put("city");
ja.put("age");

String string = "john, chicago, 22 \n"
  + "gary, florida, 35 \n"
  + "sal, vegas, 18";

JSONArray result = CDL.toJSONArray(ja, string);

Here we’ll get the contents of object result exactly as before.

The Cookie class deals with web browser cookies and has methods to convert a browser cookie into a JSONObject and vice versa.

Here are the main methods of the Cookie class:

  1. toJsonObject(String sourceCookie) – converts a cookie string into a JSONObject
  2. toString(JSONObject jo) – reverse of the previous method, converts a JSONObject into a cookie String

To convert a cookie String to a JSONObject, we’ll use the static method Cookie.toJSONObject():

String cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/";
JSONObject cookieJO = Cookie.toJSONObject(cookie);

Now we’ll convert a JSONObject into cookie String. This is the reverse of the previous step:

String cookie = Cookie.toString(cookieJO);

9. HTTP

The HTTP class contains static methods that are used to convert HTTP headers to JSONObject and vice versa.

This class also has two main methods:

  1. toJsonObject(String sourceHttpHeader) – converts a HttpHeader String to JSONObject
  2. toString(JSONObject jo) – converts the supplied JSONObject to String

9.1. Converting JSONObject to HTTP Header

HTTP.toString() method is used to convert a JSONObject to HTTP header String:

JSONObject jo = new JSONObject();
jo.put("Method", "POST");
jo.put("Request-URI", "http://www.example.com/");
jo.put("HTTP-Version", "HTTP/1.1");
String httpStr = HTTP.toString(jo);

Here is what our String httpStr will consist of:

POST "http://www.example.com/" HTTP/1.1

Note that while converting an HTTP request header, the JSONObject must contain “Method”, “Request-URI” and “HTTP-Version” keys. And for response header, the object must contain “HTTP-Version”, “Status-Code” and “Reason-Phrase” parameters.

9.2. Converting HTTP Header String Back to JSONObject

Here we will convert the HTTP string that we got in the previous step back to the very JSONObject we created in that step:

JSONObject obj = HTTP.toJSONObject("POST \"http://www.example.com/\" HTTP/1.1");

10. JSONException

The JSONException is the standard exception thrown by this package whenever any error is encountered.

This is used across all classes from this package. The exception is usually followed by a message that states what exactly went wrong.

11. Conclusion

In this article, we looked at a JSON using Java — org.json — and we focused on some of the core functionality available here.

The complete code snippets used in this article can be found over on GitHub.

Course – LS (cat=JSON/Jackson)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are closed on this article!