1**. Overview**

In this article, we will be looking at the Jackson Streaming API. It supports both reading and writing, and by using it, we can write high-performance and fast JSON parsers.

On the flip-side, it is a bit difficult to use – every detail of JSON data needs to be handled explicitly in code.

2. Maven Dependency

Firstly, we need to add a Maven dependency to the jackson-core:

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

3. Writing to JSON

We can write JSON content directly to the OutputStream by using a JsonGenerator class. Firstly, we need to create the instance of that object:

ByteArrayOutputStream stream = new ByteArrayOutputStream();
JsonFactory jfactory = new JsonFactory();
JsonGenerator jGenerator = jfactory
  .createGenerator(stream, JsonEncoding.UTF8);

Next, let’s say that we want to write a JSON with the following structure:

{  
   "name":"Tom",
   "age":25,
   "address":[  
      "Poland",
      "5th avenue"
   ]
}

We can use an instance of the JsonGenerator to write specific fields directly to the OutputStream:

jGenerator.writeStartObject();
jGenerator.writeStringField("name", "Tom");
jGenerator.writeNumberField("age", 25);
jGenerator.writeFieldName("address");
jGenerator.writeStartArray();
jGenerator.writeString("Poland");
jGenerator.writeString("5th avenue");
jGenerator.writeEndArray();
jGenerator.writeEndObject();
jGenerator.close();

To check if proper JSON was created, we can create a String object with JSON object in it:

String json = new String(stream.toByteArray(), "UTF-8");
assertEquals(
  json, 
  "{\"name\":\"Tom\",\"age\":25,\"address\":[\"Poland\",\"5th avenue\"]}");

4. Parsing JSON

When we get a JSON String as an input, and we want to extract specific fields from it, a JsonParser class can be used:

String json
  = "{\"name\":\"Tom\",\"age\":25,\"address\":[\"Poland\",\"5th avenue\"]}";
JsonFactory jfactory = new JsonFactory();
JsonParser jParser = jfactory.createParser(json);

String parsedName = null;
Integer parsedAge = null;
List<String> addresses = new LinkedList<>();

We want to obtain parsedName, parsedAge, and addresses fields from input JSON. To achieve this, we need to handle low-level parsing logic and implement it ourselves:

while (jParser.nextToken() != JsonToken.END_OBJECT) {
    String fieldname = jParser.getCurrentName();
    if ("name".equals(fieldname)) {
        jParser.nextToken();
        parsedName = jParser.getText();
    }

    if ("age".equals(fieldname)) {
        jParser.nextToken();
        parsedAge = jParser.getIntValue();
    }

    if ("address".equals(fieldname)) {
        jParser.nextToken();
        while (jParser.nextToken() != JsonToken.END_ARRAY) {
            addresses.add(jParser.getText());
        }
    }
}
jParser.close();

Depending on the field name, we are extracting it and assigning to a proper field. After parsing the document, all fields should have correct data:

assertEquals(parsedName, "Tom");
assertEquals(parsedAge, (Integer) 25);
assertEquals(addresses, Arrays.asList("Poland", "5th avenue"));

5. Extracting JSON Parts

Sometimes, when we’re parsing a JSON document, we are interested in only one particular field.

Ideally, in these situations, we want to only parse the beginning of the document, and once the needed field is found, we can abort processing.

Let’s say that we are interested only in the age field of the input JSON. In this case, we can implement parsing logic to stop parsing once needed field is found:

while (jParser.nextToken() != JsonToken.END_OBJECT) {
    String fieldname = jParser.getCurrentName();

    if ("age".equals(fieldname)) {
        jParser.nextToken();
        parsedAge = jParser.getIntValue();
        return;
    }

}
jParser.close();

After processing, the only parsedAge field will have a value:

assertNull(parsedName);
assertEquals(parsedAge, (Integer) 25);
assertTrue(addresses.isEmpty());

Thanks to that, parsing of the JSON document will be a lot faster because we do not need to read the whole document but only small part of it.

6. Conclusion

In this quick article, we’re looking at how we can leverage the Stream Processing API out of Jackson.

The implementation of all these examples and code snippets can be found over on GitHub – this is a Maven project, so it should be easy to import and run as it is.