How to Parse JSON in Java

parse JSON in JavaThis article is an overview of Java JSON libraries.

You’ll learn how to parse (decode) JSON in Java – string to object representation.

I’ll explain 2 approaches of parsing JSON in Java and what is a best Java JSON library for each case.

But first of all, let’s define what is a JSON and why do you need it.

JSON is a text-based data exchange format.

It defines only two data structures: objects and arrays.

An object is a set of name-value pairs, and an array is a list of values.

JSON defines seven value types: string, number, object, array, true, false, and null.

It was introduced in JavaScript world as a replacement for the XML format, but now it is widely spread.

JSON is often used as a common format to serialize and deserialize data in applications that communicate with each other over the Internet.

So it is more compact and lightweight alternative to XML and de-facto standard for REST API.

JSON Parsers in Java

There are two main approaches to generate and parse JSON in Java:

Object model:
The parser creates tree-like object model in memory that represents JSON document.
This gives an access to all content of JSON document by navigating tree structure, but it consumes a lot of memory as the whole document has to be loaded.
The object model generates JSON output by navigating the entire tree at once.
Streaming model:
The event-based parser uses Streaming API.
The parser reads JSON document one element step by step.
It generates an event when found specific key or value.
This approach is preferable if we don’t need all information from JSON document but search for something specific.
The Streaming API generates JSON output to a given stream by making a function call with one element at a time.

Usually, JSON Java libraries provide a quite simple processing flow:

  • You should read a string (input stream, byte array etc.) using JSON reader into the JSON object.
  • You can iterate through object properties and extract the data

Java API for JSON Processing

The Java API for JSON Processing (JSON-P) is described in JSR 353.

The implementation was introduced in Java EE 7.

Of course, you can use this API in Java SE environment, but in this case, you need to add to your application classpath corresponding library, that implement JSON-P API.

You can download it here:

https://github.com/javaee/jsonp/tree/master/impl

Adding JSON-P API library in Maven environment is easy and absolutely straightforward, as usual:

Let’s create small example how to create JSON file and parse it with help of JSON-P library:

First,  we create a map with configuration settings and generate JsonBuilderFactory factory, it will provide numerous builders, such as createObjectBuilder and createArrayBuilder.

Thee main JSON-P API entry point is singleton JSON class.

Next, with help of factory, we generate a JSON representation of an object, which consists all JSON types: string, number, object, array, true, false, and null.

After that, JsonObject can be used for writing with help of JsonWriter, which is once again provided by WriterFactory:

For simplicity, we are using System.out output as a target in this example.

the output is:

Looks quite easy.

But be careful with BigDecimal class, use scale() method to restrict a number of digits.

As it was told before, we can use two different approaches to read values in JSON format: Streaming and Object model. JSON-P supports both of them.

Let’s try to read values we stored with help of Object model approach.

As a source we are using generated JSON we already have.

First, we need JsonWriter:

Since we have no settings for a reader, we don’t need to use a factory.

So, let’s read data from JsonReader and print it to system output:

Once again, looks simple, but pay attention to the default value, defined in methods call as the second parameter.

As you can see, we read the whole object from a reader and created JSON document’s representation JsonObject.

It gives an ability to read all supported by JSON format types, and from these pieces, we could restore quite complicated objects.

In a case when we have a huge file in JSON format, and we interesting only in small part of data, this approach is not effective.

So, Streaming API comes to the stage.

There is an example of using Streaming API:

Once again, we need a reader with JSON content and JSON class, which provide us instance of JsonParser:

We could iterate through JSON content and react to events:

there are 10 types of events:

so, for simple types such as strings and numbers, all is straightforward:

for arrays and objects situation is more complicated, lets read all string values in an array:

look at the output of example:

it returns ALL string values we have in array, including string values of object's fields. So you should be careful, and check twice that you filtered out unnecessary data.

There is a problem in restoring objects from JSON: it is a boring, verbose and error-prone procedure. Next, we will find someone who helps us!

Jackson library

Jackson framework is famous as lightweight and fast implementation.

It provides both Streaming API and Tree Model approach to read JSON data, and it provides conversation from JSON to/from Plain Old Java Object (POJO).

For Data binding, it uses annotations and getter/setter methods.

For using Jackson library you need 3 jar files:

jackson-core.jar,  jackson-annotations, jackson-databind

You can find them here: https://github.com/FasterXML/ All you need is to add them to your app classpath.

Serialize objects

Suppose, we decided to get rich and become a drug car dealer.

So, one of a task we could face is providing to ours web-client info about the car in JSON format.

Let’s create Car class, which represents a car entity, and create a string with JSON representation of Car object:

the output is:

Its a magic, isn’t it?

Let’s have a look at Car, Engine and Tyre class.

Every class has getter methods for its values.

They look redundant, but if we comment at least one of them, Car.getTyres() for example, we will get:

As shown, Tyres info is gone.

Actually, Jackson framework uses getter methods of an object as one of implicit instruction how to create its JSON representation, or, in other words, to serialize it.

Suppose, we don’t need to provide Tyres field of Car object, but we need a getter for Tyres field. Jackson framework supports a flexible mechanism to customize object’s JSON representation.

So, let’s restore Car.getTyres() method, but add annotation @JsonIgnoreProperties to Car class:

the output is:

The same result we can achieve by field annotation @JsonIgnore:

With help of @JsonIgnoreType annotation, we even could forbid whole class to be serialized, for example, we can mark Engine class:

in this case, Engine info will be omitted.

There are couple notes:

First, if we mark Tyres class by @JsonIgnoreType, tyres field will be present in JSON since its type is an array: Tyres[].

Second, if we have no access to class sources, and have no ability to mark it with @JsonIgnoreType we can use Jackson dark magic mixins.

For example, lets exclude Tyres[].class from serialisation:

At first, let’s create a mixin class:

add it to JSON mapper:

the output is:

Jackson framework gives us really fine grade control on serializing objects.

For example, we want to filter out some data before serializing based on its value.

Suppose, we are going to serialize two instances of Cars class newCar and oldCar, and we want to serialize mileage field only if it less than 10000 miles.

If not, we just omit this info, a client should get the whole picture about a not-so-new car in increment…

As a first step, we have to create a class, that implements PropertyFilter interface.

It is convenient to use SimpleBeanPropertyFilter class, it implements PropertyFilter:

Next, we will mark Car class, that it is affected by the filter with name “mileageFilter”:

and we have to attach a created filter to FiterProvider:

so, there is full example source:

the output is:

Its a magic, I told you!

Parse and bind

Another very common task you can face during implementing web application is reading JSON string and parse it to object (to deserialize it).

Jackson provides an API that looks similar to JSON-P framework.

You can use Tree Model approach. in this case, we can use Jackson Framework for creating a tree of JsonNode objects which represent JSON entities.

The framework provides an ability to traverse the tree and get values of nodes.

For example, let’s restore some values from the serialized instance of Car class:

the output is:

As you can see, we can traverse tree step by step or search for JsonNode object by specific criteria.

Actually, there are tons of useful methods for searching and getting nodes value, but it is senseless to rewrite Jackson documentation here.

It is not a great surprise that restoring the Car class could be really boring and time-consuming.

So I have a good news for you – Jackson framework can do it for you itself (with your help, of course).

Let’s create a Car object and serialize it to string, as we already did. Next, we will try to de-serialize it.

ObjectMapper class has a very convenient method, it looks like something we need:

Let’s try to run it… Err… something went wrong.

It seems framework needs some our help for deserializing Car object properly.

First, we need to provide a default constructor for all classes we are going to de-serialize.

Next, we need to provide info for framework how to parse object’s properties.

The common way is getter methods.

Jackson is smart enough to resolve properties name and type from getter method.

But we should be very careful with naming convention: for example, Car’s field isNavigationSystem is not so good, it confuses Jackson, so let’s rename it:

and at last, for debugging purposes only, let’s add toString() methods to Car, Tyre and Engine classes, there is final listing:

the output is:

Jackson DeserializationFeature

Jackson Framework provides an ability to customize deserialization (reading JSON into Java Objects) on a per-call basis by a set of DeserializationFeatures for ObjectReader.

You can also change defaults for ObjectMapper, to be used as the base for all ObjectReader instances, using enable(feature), disable(feature) and configure(feature, state) methods.

There are plenty of features, you can check their description in Jackson Framework documentation

Conclusion

Summing it up, you could see Java provides to programmer very robust and powerful tools for processing data in JSON format.

You can use different approaches for parsing data depend on your needs and save a lot of time by implicit (but configurable) data binding and pay not too much attention to this task.

Scroll Up