Java Json Processing API Tutorial (JSONP)

1- What is JSON?

JSON (JavaScript Object Notation) is a data-structured text, its elements are a pair of keys and values, its value could also be another element (key & value) ,  values can also be an array.
This is a  structure of JSON data:
{
"name" : "Tran",
"address" : "Hai Duong, Vietnam",
"phones" : [0121111111, 012222222]
}
Example with nested key-value pairs:
{
 "id": 111 ,
 "name":"Microsoft",
 "websites": [
    "http://microsoft.com",
    "http://msn.com",
    "http://hotmail.com"
 ],
 "address": {
    "street":"1 Microsoft Way",
    "city":"Redmond"
 }
}

2- Các thư viện phân tích Json

There are many open source Java libraries which help you to parse the Json data. Below is a list of library like so:
  1. json.org
  2. Jackson
  3. Google GSON
  4. json-lib
  5. javax json
  6. json-simple
  7. json-smart
  8. flexjson
  9. fastjson

3- Json Processing API

JSON Processing (JSR-353) API is introduced in specification of Java EE 7 , which means that its libraries is available on the Web Server compatible with Java EE 7. You can also download these libraries or using Maven

With Maven:

<!-- http://mvnrepository.com/artifact/org.glassfish/javax.json -->
<dependency>
   <groupId>org.glassfish</groupId>
   <artifactId>javax.json</artifactId>
   <version>1.0.4</version>
</dependency>
JSON-P is divided into two core APIs:
  1. API  Streaming (javax.json.stream),
  2. JSON API Object Model (javax.json).
Streaming API is used to parse the JSON document browser from top to bottom, and emit events when it analyzes each element of the document. This API is suitable for the parse of large JSON documents, because it does not store data on memory.

The  API Object Model,  is simple and easy to use API , because it uses  API Streaming  to read the entire JSON  document and generates objects in memory tree structure. This API  is suitable for the parsing small JSON documents.

4- Tạo Maven Project

You can quickly create a Maven project and declare the  use of JSON-P library
Maven library:
<!-- http://mvnrepository.com/artifact/org.glassfish/javax.json -->
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.0.4</version>
</dependency>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 http://maven.apache.org/xsd/maven-4.0.0.xsd">

 <modelVersion>4.0.0</modelVersion>

 <groupId>org.o7planning</groupId>
 <artifactId>JSONPTutorial</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>JSONPTutorial</name>
 <url>http://maven.apache.org</url>

 <properties>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 <dependencies>


   <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>3.8.1</version>
     <scope>test</scope>
   </dependency>
   
   <!-- http://mvnrepository.com/artifact/org.glassfish/javax.json -->
   <dependency>
       <groupId>org.glassfish</groupId>
       <artifactId>javax.json</artifactId>
       <version>1.0.4</version>
   </dependency>
   
   
 </dependencies>

</project>

5- Tổng quan về JSON-P

Some important interfaces of JSON API are:
Interface Description
javax.json.JsonReader You can use this to read JSON object or an array to JsonObject. And get JsonReader from Json class or JsonReaderFactory.
javax.json.JsonWriter You can use this to write JSON object to output stream.
javax.json.stream.JsonParser This works as a full parser and provide streaming support for reading JSON objects.
javax.json.stream.JsonGenerator You can use this to write JSON object to output source in streaming way.
javax.json.Json This is the factory class for creating JSON processing objects. This class provides the most commonly used methods for creating these objects and their corresponding factories. The factory classes provide all the various ways to create these objects.

6- Ví dụ với JSON-P

Here is a JSON data file:
company.txt
{
  "id": 111 ,
  "name":"Microsoft",
  "websites": [
     "http://microsoft.com",
     "http://msn.com",
     "http://hotmail.com"
  ],
  "address":{
     "street":"1 Microsoft Way",
     "city":"Redmond"
  }
}

Note: The name of the attribute should be placed in the "" (quotes), for example:

  • "Id": 111

Sometimes JSON data  have attributes are not named  in the quotes, some JSON parsers understand and allow that, however the JSON-P parser does not allow, if you use Java JSON-P to parse a JSON data that attribute's name is not in the quotes, you'll get an exception:

  • javax.json.stream.JsonParsingException: Unexpected char 105 at (line no=xx, column no=xx, offset=xx)
Address.java
package org.o7planning.jsonptutorial.beans;

public class Address {
   
   private String street;
   private String city;

   public Address() {

   }

   public Address(String street, String city) {
       this.street = street;
       this.city = city;
   }

   public String getStreet() {
       return street;
   }

   public void setStreet(String street) {
       this.street = street;
   }

   public String getCity() {
       return city;
   }

   public void setCity(String city) {
       this.city = city;
   }

   @Override
   public String toString() {
       return street + ", " + city;
   }
   
}
Company.java
package org.o7planning.jsonptutorial.beans;

public class Company {

   private int id;
   private String name;
   private String[] websites;
   private Address address;

   public int getId() {
       return id;
   }

   public void setId(int id) {
       this.id = id;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public String[] getWebsites() {
       return websites;
   }

   public void setWebsites(String[] websites) {
       this.websites = websites;
   }

   public Address getAddress() {
       return address;
   }

   public void setAddress(Address address) {
       this.address = address;
   }

   @Override
   public String toString() {
       StringBuilder sb = new StringBuilder();

       sb.append("\n id:" + this.id);
       sb.append("\n name:" + this.name);
       if (this.websites != null) {
           sb.append("\n website: ");
           for (String website : this.websites) {
               sb.append(website + ", ");
           }
       }
       if (this.address != null) {
           sb.append("\n address:" + this.address.toString());
       }
       return sb.toString();
   }

}
JsonReader is an object used to read JSON data, you can get the   JsonReader from  Json class or from  JsonReaderFactory.
InputStream input = new FileInputStream("company.txt");
 
// Create JsonReader object from Json class.
JsonReader jsonReader1 = Json.createReader(input);

// Or from Factory
JsonReaderFactory factory = Json.createReaderFactory(null);
JsonReader jsonReader2 = factory.createReader(input);
JsonReaderExample.java
package org.o7planning.jsonptutorial;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;

import org.o7planning.jsonptutorial.beans.Address;
import org.o7planning.jsonptutorial.beans.Company;

public class JsonReaderExample {
 
  public static void main(String[] args) throws IOException {
      InputStream input = new FileInputStream("company.txt");
     
      // Create JsonReader object
      JsonReader jsonReader = Json.createReader(input);
   
     
      // Get JsonObject (root object).
      JsonObject rootJSON = jsonReader.readObject();
     
      // Close resources
      jsonReader.close();
      input.close();
     
      // Create empty Company object.
      Company company = new Company();
     
      company.setId(rootJSON.getInt("id"));
      company.setName(rootJSON.getString("name"));
     
     
      // Reading websites array from json
      JsonArray jsonArray = rootJSON.getJsonArray("websites");
      String[] websites = new String[jsonArray.size()];
     
      int index = 0;
      for(JsonValue value : jsonArray){
          websites[index++] = value.toString() ;
      }
      company.setWebsites(websites);
     
      // Reading inner object from json object.
      JsonObject addressJSON = rootJSON.getJsonObject("address");
      Address address = new Address();
      address.setStreet(addressJSON.getString("street"));
      address.setCity(addressJSON.getString("city"));
   
      company.setAddress(address);
     
      // Print out information
      System.out.println(company);
     
  }

}
Run the example:

7- Ví dụ với JsonWriter

JsonWriterExample.java
package org.o7planning.jsonptutorial;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonWriter;

import org.o7planning.jsonptutorial.beans.Address;
import org.o7planning.jsonptutorial.beans.Company;

public class JsonWriterExample {

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

      Company company = createCompany();

      // Object Builder
      JsonObjectBuilder companyBuilder = Json.createObjectBuilder();
     
      // Object Builder
      JsonObjectBuilder addressBuilder = Json.createObjectBuilder();
     
      // Array Builder
      JsonArrayBuilder websitesBuilder = Json.createArrayBuilder();

      for (String website : company.getWebsites()) {
          websitesBuilder.add(website);
      }

      Address address = company.getAddress();
      addressBuilder.add("street", address.getStreet()).add("city", address.getCity() );

      companyBuilder.add("id", company.getId()).add("name", company.getName() );

      companyBuilder.add("websites", websitesBuilder);
      companyBuilder.add("address", addressBuilder);

      // Root JsonObject
      JsonObject rootJSONObject = companyBuilder.build();

      System.out.println("Root JsonObject: " + rootJSONObject);

      // Write to file
      File outFile= new File("C:/test/company2.txt");
      outFile.getParentFile().mkdirs();
     
      OutputStream os = new FileOutputStream(outFile);
      JsonWriter jsonWriter = Json.createWriter(os);
     
      jsonWriter.writeObject(rootJSONObject);
      jsonWriter.close();
  }

  public static Company createCompany() {

      Company company = new Company();
      company.setId(123);
      company.setName("Apple");

      String[] websites = { "http://apple.com"};
      company.setWebsites(websites);

      Address address = new Address();
      address.setCity("Cupertino");
      address.setStreet("1 Infinite Loop");

      company.setAddress(address);

      return company;
  }
 
}
Run the example:

8- Ví dụ với JsonParser

Above you have worked with JsonReader to read content of json file, whole content of Json is objects and stored on memory, this way is only suitable when you work with small Json data. In the case of large data you should use JsonParser to parse Json data. JsonParser work similarly to XML of SAX.  JsonParser does not store read data on the memory. 
On your code, it calls the  next() method to  JsonParser parse next element Json, it generates events when parsing one element. The parser can generate the following events:
  •  START_OBJECT
  • END_OBJECT
  • START_ARRAY
  • END_ARRAY
  • KEY_NAME
  • VALUE_STRING
  • VALUE_NUMBER
  • VALUE_TRUE
  • VALUE_FALSE
  • VALUE_NULL.
Based on the name of the emitted event, and the name of the element being parsed, you can know the position being parsed, and retrieve the values there. 

Methods that can be used in this case:

  • getString()
  • getInt()
  • ....
     
See for example:
JsonParserExample.java
package org.o7planning.jsonptutorial;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.json.Json;
import javax.json.stream.JsonParser;

import org.o7planning.jsonptutorial.beans.Address;
import org.o7planning.jsonptutorial.beans.Company;

public class JsonParserExample {

   public static void main(String[] args) throws IOException {
       InputStream inputStream = new FileInputStream("company.txt");

       JsonParser jsonParser = Json.createParser(inputStream);

       // Tạo các đối tượng, các trường của nó sẽ được sét đặt giá trị
       // mỗi khi tìm thấy giá trị trong các sự kiện.
       Company company = new Company();
       Address address = new Address();
       
       List<String> websitesList = new ArrayList<String>();
       
       // Key name của JSON.
       String keyName = null;
       
       while (jsonParser.hasNext()) {
           JsonParser.Event event = jsonParser.next();
           switch (event) {
           case KEY_NAME:
               keyName = jsonParser.getString();
               break;
           case VALUE_STRING:
               setStringValues(company, address, keyName, jsonParser.getString(), websitesList);
               break;
           case VALUE_NUMBER:
               setNumberValues(company, address, keyName, jsonParser.getInt());
               break;
           default:
               // No need..
           }
       }
       company.setAddress(address);
       String[] websites = new String[websitesList.size()];
       websitesList.toArray(websites);
       company.setWebsites(websites);

       // Print out
       // Ghi ra màn hình
       System.out.println(company);        
       inputStream.close();
       jsonParser.close();
   }

   private static void setNumberValues(Company company, Address address, String keyName, int value) {
       if (keyName.equals("id")) {
           company.setId(value);
       } else {
           System.out.println("Unknown Key:" + keyName);
       }
   }

   private static void setStringValues(Company company, Address address, String keyName, String value,
           List<String> websiteList) {
       if (keyName.equals("name")) {
           company.setName(value);
       } else if (keyName.equals("street")) {
           address.setStreet(value);
       } else if (keyName.equals("city")) {
           address.setCity(value);
       } else if (keyName.equals("websites")) {
           websiteList.add(value);
       } else {
           System.out.println("Unknown Key=" + keyName);
       }
   }

}
Running the example: