Processing JSON with JSR 353 streaming APIs

 

Processing JSON with JSR 353 streaming APIs

This category of APIs supports the streaming model for both reading and writing the JSON content. This model is designed to process a large amount of data in a more efficient way. Conceptually, this model is similar to the Streaming API for XML (StAX) parser that you might have used while dealing with the XML data.

Streaming APIs are grouped in the javax.json.stream package in the JSR specification. In this section, we will see how we can use the streaming APIs to efficiently process JSON data.

Here is a list of the frequently used classes in the streaming API provided by the JSR 353 specification:

Class

Description

javax.json.stream.JsonParser

This class provides forward read-only access to JSON data by using the pull parsing programming model.

javax.json.stream.JsonGenerator

This class writes JSON to an output source as specified by the client application. It generates the name-value pairs for the JSON objects and values for the JSON arrays.


Streaming APIs read and write the content serially at runtime in accordance with client calls, which makes them suitable for handling a large amount of data.


This example illustrates the use of streaming APIs for converting a JSON array of the employee objects present in the emp-array.json file into an appropriate Java class representation.

The following code snippet illustrates how you can use javax.json.stream.JsonParser, which follows the streaming parsing model, to read the content from the emp-array.json file:













package com.inayath;


import java.io.InputStream;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;


import javax.json.Json;


import javax.json.stream.JsonParser;

import javax.json.stream.JsonParser.Event;


public class JsonToJavaObj_StreamModel {

public static void main(String[] args) throws ParseException {


//The first step is to get the input stream for reading the emp-array.json file.

//Then, you can create a JsonParser instance with the input stream, as follows:

InputStream resourceAsStream = JsonToJavaObj_StreamModel.class.getResourceAsStream("/emp-array.json");

JsonParser jsonParser = Json.createParser(resourceAsStream);

List<Employee> employeeList = new ArrayList<>();

Employee employee = null;

//Start parsing the content now. 

//The following code snippet illustrates the API use for parsing the content with the pull parsing model:


// Returns true if there are more parsing states

while (jsonParser.hasNext()) {

// Returns the event for the next parsing state

Event event = jsonParser.next();

// Start of a JSON object,

// position of the parser is after'{'

if (event.equals(JsonParser.Event.START_OBJECT)) {

employee = new Employee();

employeeList.add(employee);

} else if (event.equals(JsonParser.Event.KEY_NAME)) {

String keyName = jsonParser.getString();

switch (keyName) {

case "firstName":

jsonParser.next();

employee.setFirstName(jsonParser.getString());

break;

case "lastName":

jsonParser.next();

employee.setLastName(jsonParser.getString());

break;

case "email":

jsonParser.next();

employee.setEmail(jsonParser.getString());

break;

case "employeeId":

jsonParser.next();

employee.setEmployeeId(jsonParser.getInt());

break;

case "hireDate":

jsonParser.next();

// Converts date string (from JSON) into

// java.util.Date object

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

Date hireDate = dateFormat.parse((jsonParser.getString()));

employee.setHireDate(hireDate);

break;

default:

}

}

}

employeeList.stream().forEach(System.out::println);

}

}

Remember that JsonParser parses JSON by using the pull parsing programming model. In this case, the client application code controls the progress of parsing. The client calls next() on JsonParser to advance the parser to the next state after processing each element. In response to the next() call from the client, the parser generates the following events on the basis of the type of the next token encountered: START_OBJECTEND_OBJECTSTART_ARRAYEND_ARRAYKEY_NAMEVALUE_STRINGVALUE_NUMBERVALUE_TRUEVALUE_FALSE, and VALUE_NULL.

To better understand this, consider the following JSON array as the input to the parser:

[{"country": "IN"}] 

The parser generates the START_ARRAY event for the first call to the next() method and the START_OBJECT event with the second call to the next() method, and so on. The following diagram illustrates the events generated while parsing each token present in the JSON representation:




Comments

Popular posts from this blog

Understanding the JAX-RS resource life cycle

Generating a chunked output using Jersey APIs

Jersey client API for reading chunked input