Nov 162014
 
Article Java

JSON is a format commonly used for the interchange of data between applications.. The easiest way to process a JSON file is by means of a parser that read the whole document in memory, as a tree of data structures.

But sometimes the volume of data in the JSON file is too big, and the available memory resources are not enough to use this procedure. In those cases, the data must be read as a stream, to process the content of the JSON file sequentially, one element at a time.

This post is an introduction to the Java “Jackson” library, that enables this type of sequential processing of a JSON file in a Java program.

1. Downloading and installing the Jackson Core library

The modules of the Jackson library can be downloaded from the Maven Central Repository.

First, download the file jackson-core-2.4.3.jar, that contains the latest stable version of Jackson Core (Jackson 2.4.3, de 04-Oct-2014) as the Jackson Home page on github states.

Optionally, the documentation in the jackson-core-2.4.3-javadoc.jar file can also be downloaded from the same URL.

2. Creating a parser object to read the content of the JSON document

To create a parser for a JSON document, a JacksonFactory object is created, and a JsonParser object is retrieved using the “createParser()” method of the factory object. For instance, to read a file “data.json”, the following code can be used:

import java.io.File;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

public class LeeJsonStream {
    public static void main(String[] args) throws IOException {
        JsonFactory factory = new JsonFactory();
        JsonParser parser = factory.createParser(new File("data.json"));
            ...
    }
}

Note: In the above example, the argument to createParser() is a File object. We could have used also as argument an InputStream or URL object. For instance, if the document to be processed is retrieved from the url “http://www.ejemplo.com/data.json”, the call to createParser would be written as:

    JsonParser parser = factory.createParser(new URL("http://www.ejemplo.com/data.json"));

2. Read loop

Next, the document is read by retrieving the elements one at a time with a call to parser.nextToken() in a while loop, until the end of the file is reached:

    while (!parser.isClosed()) {
        // read the next element
        JsonToken token = parser.nextToken();
        // if the call to nextToken returns null, the end of the file has been reached
        if (token == null)
            break;

        // Process the element
         String indent = "";
         processJSONValue(token, parser, indent);
    }

3. Processing a JSON element

The type of processing of a token retrieved with nextToken() depends on the type of token. In the JsonToken class, the possible types of token are defined as a set of constants:

  • START_OBJECT, END_OBJECT – Returned for tokens “{” y “}”
  • START_ARRAY, END_ARRAY – Returned for tokens “[” y “]”
  • FIELD_NAME – The name of a field in a JSON object
  • VALUE_NULL – “null” literal
  • VALUE_FALSE, VALUE_TRUE – “false”, “true” literals
  • VALUE_NUMBER_INT, VALUE_NUMBER_FLOAT – integer and floating point number values
  • VALUE_STRING – String values

The code below implements three simple methods processJSONObject(), processJSONArray() and processJSONValue(), that output to screen an indented dump of the JSON object being read:

 private static void processJSONObject(JsonParser parser, String indent)
                     throws IOException {
     System.out.println(margin + "JSON Object");
     indent += " ";
     while (!parser.isClosed()) {
         JsonToken token = parser.nextToken();
         if (JsonToken.END_OBJECT.equals(token)) {
             //The end of the JSON object has been reached
             break;
         }
         if (!JsonToken.FIELD_NAME.equals(token)) {
             System.out.println("Error. Expected a field name");
             break;
         }
         System.out.println(indent + "Field: " + parser.getCurrentName());
         token = parser.nextToken();
         processJSONValue(token, parser, indent);
     }
 }

 private static void processJSONArray (JsonParser parser, String margin)
                     throws IOException {
     System.out.println(margin + "JSON Array");
     indent += " ";
     while (!parser.isClosed()) {
         JsonToken token = parser.nextToken();
         if (JsonToken.END_ARRAY.equals(token)) {
             // The en of the array has been reached
             break;
         }
         processJSONValue(token, parser, indent);
     }
 }

 private static void processJSONValue (JsonToken token, JsonParser parser, String indent)
                     throws IOException {
     if (JsonToken.START_OBJECT.equals(token)) {
         processJSONObject(parser, indent);
     } else if (JsonToken.START_ARRAY.equals(token)) {
         processJSONArray(parser, indent);
     } else {
         System.out.println(margen + "Value: " + parser.getValueAsString());
     }
 }

As we can see, if the value being read by processJSONValue() is a JSON object or a JSON array, the methods processJSONObject() and processJSONArray() are recursively called.

If the value being read is a boolean, number or string, it is just printed calling the method getValueAsString().

References

Index of posts related to Java programming

 Posted by at 12:50 pm

 Leave a Reply

(required)

(required)