Saturday, November 16, 2024
Google search engine
HomeLanguagesJavaHow to Generate JSON with JsonGenerator in Java?

How to Generate JSON with JsonGenerator in Java?

The JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax. It is lightweight, flexible, and faster than XML, which is the reason that it is used widely for data interchange between server and client. If you ever work on Java Enterprise Applications then you will come across tasks where you might need to generate and parse JSON data for your application. For instance, RESTful web services use JSON extensively as the format for the data inside requests and responses.

The following examples show a JSON object with name-value pairs:

{
   "firstName": "Duke",
   "lastName": "Java",
   "age": 18,
   "streetAddress": "100 Internet Dr",
   "city": "JavaTown",
   "state": "JA",
   "postalCode": "12345",
   "phoneNumbers": [
      { "Mobile": "111-111-1111" },
      { "Home": "222-222-2222" }
   ]
}

Java provides an API to parse, transform, and query JSON data using either the object model or the streaming model.

The object model works by creating a tree that represents the JSON data in memory. The object model generates JSON output by navigating the entire tree at once and hence, allows for processing that requires access to the entire contents of the tree at once. The tree can be navigated, analyzed, or modified. This approach is considered flexible but it is slower than the streaming model and requires more memory.

Java API provides the javax.json package, it contains a reader interface, a writer interface, and a model builder interface for the object model. The package also contains other utility classes and Java types for JSON elements.

In the object model, a JSON-object reference is created which represents the root of the tree and can be used to navigate the tree or to write it to a stream as JSON data. This JSON-object reference created can either be of type JsonObject or JsonArray, and both of them are the subtypes of JsonStructure. Which one it will depend on the format/content of the file. 

Let’s describe each of them to be precise and clear.

Let us go through some traits of JsonObject

  • Written in key-value pairs.
  • Keys must be strings and values must be valid JSON type.
  • JsonObject starts and ends with curly braces { }.
  • Order is not important.

Sample code for JSON object is as follows in below illustration

{
    "name" : "Lazyroar",
    "description" : "An educational website"
}

Let us go through some traits of JsonArray

  • Used to organize a collection of related items.
  • Values can be of type string, number, object, array, boolean, or null.
  • JsonArray starts and ends with square brackets [ ].
  • Order is important.

Illustration:

[1, 2, 3, 4]

JsonObject and JsonArray can also be used in a nested manner to represent some special kind of data. You can either use the object inside the array or the array inside the object.

{
    "employees":[
        {"firstName":"John", "lastName":"Doe"},
        {"firstName":"Anna", "lastName":"Smith"},
        {"firstName":"Peter", "lastName":"Jones"}
    ],
    "positions" : [
        {"department" : "Testing", "role" : "Junior"},
        {"department" : "Testing", "role" : "Senior"},
        {"department" : "Design", "role" : "Junior"}
    ] 
}

Now that we are clear with the basics, we can learn how to code.

Now let us come onto installing javax.json API. So, If you are using a Maven project then add this dependency to your pom.xml file:

<dependency>
    <groupId>javax.json</groupId>
    <artifactId>javax.json-api</artifactId>
    <version>1.1.4</version>
</dependency>

Otherwise, in case you are creating a normal project then add the javax.json jar to your Libraries else download the jar file from here and follow the below steps

Step 1: Creating Object model from given JSON data

if we assume that we already have some data in the JSON format, and thus want to convert that into a java JsonObject, then we can make use of the javax.json.JsonStructure.

Let us assume we have a sample.txt that stores JSON data as follows:

{
  "firstName": "John",
  "lastName": "Smith",
  "age": 25,
  "address": {
    "streetAddress": "21 2nd Street",
    "city": "New York",
    "state": "NY",
    "postalCode": "10021"
  },

  "phoneNumber":
  [

  {
    "type":"home",
    "number":"212 555-1234"
  },

  {
    "type": "fax",
    "number": "646 555-4567"
  }
  ]
}

Apart from just creating an object of the data, we need to have a way to read that data as well! 

Step 2: Navigate it.

For navigating the data we will create a function navigateTree() that will take the JSON object/model that we created, as an input, and for every object or array that it encounters nested inside the JSON model, it will call the navigating function again, and if the element is a value, then it will print the standard output.

Now we can proceed to code for creating a JsonStructure out of this sample.txt file which is as shown below

Example 

Java




// Java Program to create a JsonStructure of an already
// existing data in the JSON format
 
// Importing required classes
import java.io.FileNotFoundException;
import java.io.FileReader;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonString;
import javax.json.JsonStructure;
import javax.json.JsonValue;
 
// Main class
public class CreateObjectModelFromJSONData {
 
    // Main driver method
    public static void main(String args[])
        throws FileNotFoundException
    {
 
        // JsonReader: an interface that reads a JSON object
        // or an array structure from an input source.
 
        JsonReader reader = Json.createReader(
            new FileReader("sample.txt"));
 
        // JsonStructure: an interface that is a super type
        // for the two structured types in JSON
        // (objects and arrays)
        JsonStructure jsonst = reader.read();
 
        // navigateTree method takes two arguments: a JSON
        // element and a key. The key is used only to help
        // print the key-value pairs inside objects.
        // Elements in a tree are represented by the
        // JsonValue type.
 
        navigateTree(jsonst, null);
    }
 
    // A JsonValue is one of the following: an object
    // (JsonObject), an array (JsonArray), a number
    // (JsonNumber), a string (JsonString), true
    // (JsonValue.TRUE), false (JsonValue.FALSE), or null
    // (JsonValue.NULL).
 
    // Method 2
    // To navigate through the model
    // and print the key-value pairs
    public static void navigateTree(JsonValue tree,
                                    String key)
    {
        if (key != null)
            System.out.print("Key " + key + ": ");
 
        // Switch case
 
        // Method 3
        // getValueType() returns the value type of
        // this JSON value.
        switch (tree.getValueType()) {
 
        // Case 1
        case OBJECT:
 
            System.out.println("OBJECT");
            JsonObject object = (JsonObject)tree;
 
            for (String name : object.keySet())
                navigateTree(object.get(name), name);
 
            break;
 
        // Case 2
        case ARRAY:
 
            System.out.println("ARRAY");
            JsonArray array = (JsonArray)tree;
 
            for (JsonValue val : array)
                navigateTree(val, null);
 
            break;
 
        // Case 3
        case STRING:
 
            JsonString st = (JsonString)tree;
 
            System.out.println("STRING " + st.getString());
            break;
 
        // Case 4
        case NUMBER:
 
            JsonNumber num = (JsonNumber)tree;
            System.out.println("NUMBER " + num.toString());
 
            break;
 
        // Case 5
        case TRUE:
 
        // Case 6
        case FALSE:
 
        // Case 7
        case NULL:
 
            // Print statement
            System.out.println(
                tree.getValueType().toString());
            break;
        }
    }
}


 
Output 

OBJECT
Key firstName: STRING John
Key lastName: STRING Smith
Key age: NUMBER 25
Key address: OBJECT
Key streetAddress: STRING 21 2nd Street
Key city: STRING New York
Key state: STRING NY
Key postalCode: STRING 10021
Key phoneNumber: ARRAY
OBJECT
Key type: STRING home
Key number: STRING 212 555-1234
OBJECT
Key type: STRING fax
Key number: STRING 646 555-4567

2. Creating an object model from code

In order to create an object model of our own from scratch we will make use of the JSON class that provides a method createObjectBuilder() that creates a JSON object builder.  The JsonObjectBuilder interface acts as a builder for creating JsonObject models from scratch. This interface initializes an empty JSON object model and provides methods to add name/value pairs to the object model and to return the resulting object. The methods in this class can be chained to add multiple name/value pairs to the object.

Example 

Java




// Java Program to create a Json object from scratch using
// JsonObjectBuilder and navigate it.
 
// Importing required classes
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonString;
import javax.json.JsonValue;
 
// Main class
// CreateObjectModelFromCode
public class GFG {
 
    // Method 1
    // Main driver method
    public static void main(String args[])
    {
 
        // add() method adds a name/value pair to the JSON
        // object associated with this object builder.
        // build() method returns the JSON object associated
        // with this object builder.
        JsonObject model
            = Json.createObjectBuilder()
                  .add("firstName", "Duke")
                  .add("lastName", "Java")
                  .add("age", 18)
                  .add("streetAddress", "100 Internet Dr")
                  .add("city", "JavaTown")
                  .add("state", "JA")
                  .add("postalCode", "12345")
                  .add("phoneNumbers",
                       Json.createArrayBuilder()
                           .add(Json.createObjectBuilder()
                                    .add("type", "mobile")
                                    .add("number",
                                         "111-111-1111"))
                           .add(Json.createObjectBuilder()
                                    .add("type", "home")
                                    .add("number",
                                         "222-222-2222")))
                  .build();
 
        // The same navigateTree() method can be used to
        // navigate this model.
        navigateTree(model, null);
    }
 
    // Method 2
    public static void navigateTree(JsonValue tree,
                                    String key)
    {
        if (key != null)
            System.out.print("Key " + key + ": ");
 
        // Method 3- getValueType()
        // To get the value types
 
        // Switch case
        switch (tree.getValueType()) {
 
        // Case 1
        case OBJECT:
 
            System.out.println("OBJECT");
 
            JsonObject object = (JsonObject)tree;
 
            for (String name : object.keySet())
                navigateTree(object.get(name), name);
            break;
 
        // Case 2
        case ARRAY:
 
            System.out.println("ARRAY");
 
            JsonArray array = (JsonArray)tree;
 
            for (JsonValue val : array)
                navigateTree(val, null);
            break;
 
        // Case 3
        case STRING:
 
            JsonString st = (JsonString)tree;
 
            System.out.println("STRING " + st.getString());
            break;
 
        // Case 4
        case NUMBER:
 
            JsonNumber num = (JsonNumber)tree;
 
            System.out.println("NUMBER " + num.toString());
            break;
 
        // Case 5
        case TRUE:
 
        // Case 6
        case FALSE:
 
        // Case 7
        case NULL:
 
            System.out.println(
                tree.getValueType().toString());
            break;
        }
    }
}


Output 

OBJECT
Key firstName: STRING Duke
Key lastName: STRING Java
Key age: NUMBER 18
Key streetAddress: STRING 100 Internet Dr
Key city: STRING JavaTown
Key state: STRING JA
Key postalCode: STRING 12345
Key phoneNumbers: ARRAY
OBJECT
Key type: STRING mobile
Key number: STRING 111-111-1111
OBJECT
Key type: STRING home
Key number: STRING 222-222-2222

3. Writing Object model to a Stream

The object models that we created in the above examples can be written to a stream using the JsonWriter class. JsonWriter writes a JSON object or array structure to an output source. This time we will write the contents of the sample.txt to an output stream after we have converted it to a JsonStructure.

Example 

Java




// Java Program to Write the Object Model to an Output Stream
 
// Importing required classes
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.StringWriter;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonStructure;
import javax.json.JsonWriter;
 
// Main class
// WritingObjectModelToAStream
public class GFG {
 
    // Main driver method
    public static void main(String args[])
        throws FileNotFoundException
    {
 
        JsonReader reader = Json.createReader(
            new FileReader("sample.txt"));
        JsonStructure jsonst = reader.read();
 
        StringWriter stWriter = new StringWriter();
 
        // We use try-with-resources to close the JSON
        // writer automatically
 
        // Json.createWriter() method takes an output stream
        // as a parameter. JsonWriter.writeObject() method
        // writes the object to the stream.
 
        // Try block to check for exceptions
        try (JsonWriter jsonWriter
             = Json.createWriter(stWriter)) {
            jsonWriter.writeObject((JsonObject)jsonst);
        }
 
        // Creating variable jsonData to store the object
        // written to the stream in the form of a String
        String jsonData = stWriter.toString();
 
        // Print the data string
        System.out.println(jsonData);
    }
}


 
Output: On the console, the following will be printed in a single line 

{
"firstName":"John","lastName":"Smith","age":25,
"address":{"streetAddress":"21 2nd Street","city":"New York","state":"NY","postalCode":"10021"},
"phoneNumber":[{"type":"home","number":"212 555-1234"},{"type":"fax","number":"646 555-4567"}]
}

Now dwelling onto next model, 

The streaming model uses an event-based parser that reads JSON data one element at a time. The streaming model generates JSON output to a given stream by making a function call with one element at a time. This approach is adequate for local processing, in which the processing of an element does not require information from the rest of the data. The way it works is that the parser generates events and stops for processing whenever it either finds a key, or finds a value, or reaches the beginning or end of an object or array. The element found can be processed or discarded based on the code and then the parser moves to the next event.

The Java API provides the javax.json.stream package, it contains a parser interface, JsonParser, and a generator interface, JsonGenerator for the streaming model. The interface JsonParser contains methods to parse JSON in a streaming way. The interface JsonGenerator contains methods to write JSON to an output source in a streaming way. 

In the upcoming code, we will make use of the same sample.txt file to parse it.

1. Reading JSON data using a Parser: We will use the JsonParser that provides forward, read-only access to JSON data in a streaming way. JsonParser parses JSON using the pull parsing programming model. In this model, the client code controls the thread and calls the method next() to advance the parser to the next state after processing each 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, and VALUE_NULL.

In the following code we will perform the following steps: 

  1. Get the JSON data in the form of a String, so that it can be passed to the parser object.
  2. Obtain a parser instance by calling the JSON.createParser static method and pass the string to it.
  3. Iterate over the parser events with the JsonParser.hasNext and the JsonParser.next methods.
  4. Perform local processing for each element.

Implementation:

Example 

Java




// Java program to Read JSON data using a JsonParser
 
// Importing required classes
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.StringReader;
import java.io.StringWriter;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonStructure;
import javax.json.JsonWriter;
import javax.json.stream.JsonParser;
 
// Main class
// ReadingJSONDataUsingAParser
public class GFG {
 
    // Main driver method
    public static void main(String args[])
        throws FileNotFoundException
    {
 
        // Creating object of JsonReader class
        // Creating object of JsonStructure class
        JsonReader reader = Json.createReader(
            new FileReader("sample.txt"));
        JsonStructure jsonst = reader.read();
 
        StringWriter stWriter = new StringWriter();
 
        // Try block to check for exceptions
        try (JsonWriter jsonWriter
             = Json.createWriter(stWriter)) {
            jsonWriter.writeObject((JsonObject)jsonst);
        }
 
        // Step 1
        String jsonData = stWriter.toString();
 
        // Step 2
        // Json.createParser(): Creates a JSON parser from a
        // character stream.
        JsonParser parser
            = Json.createParser(new StringReader(jsonData));
 
        // Step 3
        // haNext(): Returns true if there are more parsing
        // states. This method returns false if the parser
        // reaches the end of the JSON text
        while (parser.hasNext()) {
 
            // JsonParser.Event: An event from JsonParser.
            // next(): Returns the event for the next
            // parsing state.
            JsonParser.Event event = parser.next();
 
            // Step 4
 
            // Switch case
            switch (event) {
 
            // Case 1
            // Start of a JSON array.
            case START_ARRAY:
 
            // Case 2
            // End of a JSON array.
            case END_ARRAY:
 
            // Case 3
            // Start of a JSON object.
            case START_OBJECT:
 
            // Case 4
            // End of a JSON object.
            case END_OBJECT:
 
            // Case 5
            // False value in a JSON array or object.
            case VALUE_FALSE:
 
            // Case 6
            // Null value in a JSON array or object.
            case VALUE_NULL:
 
            // Case 7
            // True value in a JSON array or object.
            case VALUE_TRUE:
                System.out.println(event.toString());
                break;
 
            // Case 8
            // Name in a name/value pair of a JSON object.
            case KEY_NAME:
                System.out.print(event.toString() + " "
                                 + parser.getString()
                                 + " - ");
                break;
 
            // Case 9
            // String value in a JSON array or object.
            case VALUE_STRING:
 
            // Case 10
            // Number value in a JSON array or object.
            case VALUE_NUMBER:
                System.out.println(event.toString() + " "
                                   + parser.getString());
                break;
            }
        }
    }
}


 
Output: 

START_OBJECT
KEY_NAME firstName - VALUE_STRING John
KEY_NAME lastName - VALUE_STRING Smith
KEY_NAME age - VALUE_NUMBER 25
KEY_NAME address - START_OBJECT
KEY_NAME streetAddress - VALUE_STRING 21 2nd Street
KEY_NAME city - VALUE_STRING New York
KEY_NAME state - VALUE_STRING NY
KEY_NAME postalCode - VALUE_STRING 10021
END_OBJECT
KEY_NAME phoneNumber - START_ARRAY
START_OBJECT
KEY_NAME type - VALUE_STRING home
KEY_NAME number - VALUE_STRING 212 555-1234
END_OBJECT
START_OBJECT
KEY_NAME type - VALUE_STRING fax
KEY_NAME number - VALUE_STRING 646 555-4567
END_OBJECT
END_ARRAY
END_OBJECT

2. Writing JSON Data using Generator

Using the JsonGenerator we can write JSON data to an output source in a streaming way. Obtain a JSON generator by calling the Json.createGenerator static method, which takes a writer or an output stream as a parameter. We will write the JSON data to a details.txt file.

Example

Java




// Java Program to Generate JSON data and Store it into a
// file.
 
// Importing required classes
import java.io.FileWriter;
import java.io.IOException;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
 
// Main class
// WriteJSONDataUsingGenerator
public class GFG {
 
    // Main driver method
    public static void main(String args[])
    {
 
        FileWriter writer = null;
 
        // Try block to check for exceptions
        try {
 
            writer = new FileWriter("details.txt");
        }
 
        // Catch block to handle i/o exceptions
        catch (IOException e) {
 
            // Print the exceptions along with line number
            // using printStackTrace() method
            e.printStackTrace();
        }
 
        // Json.createGenerator(): Creates a JSON generator
        // for writing JSON to a character stream.
        JsonGenerator generator
            = Json.createGenerator(writer);
 
        // writeStartObject(): Writes the JSON name/start
        // object character pair in the current object
        // context. write(): Writes a JSON name/string value
        // pair in the current object context. writeEnd():
        // Writes the end of the current context.
        // writeStartArray(): Writes the JSON name/start
        // array character pair with in the current object
        // context.
 
        generator.writeStartObject()
            .write("firstName", "John")
            .write("lastName", "Smith")
            .write("age", 25)
            .writeStartObject("address")
            .write("streetAddress", "21 2nd Street")
            .write("city", "New York")
            .write("state", "NY")
            .write("postalCode", "10021")
            .writeEnd()
            .writeStartArray("phoneNumber")
            .writeStartObject()
            .write("type", "home")
            .write("number", "212 555-1234")
            .writeEnd()
            .writeStartObject()
            .write("type", "fax")
            .write("number", "646 555-4567")
            .writeEnd()
            .writeEnd()
            .writeEnd();
 
        // Closes this generator and frees any resources
        // associated with it using close() method
        generator.close();
    }
}


Output: In the details.txt file the following data will be written in a single line: 

{
"firstName":"John","lastName":"Smith","age":25,
"address":{"streetAddress":"21 2nd Street","city":"New York","state":"NY","postalCode":"10021"},
"phoneNumber":[{"type":"home","number":"212 555-1234"},{"type":"fax","number":"646 555-4567"}]
}

 

Dominic Rubhabha-Wardslaus
Dominic Rubhabha-Wardslaushttp://wardslaus.com
infosec,malicious & dos attacks generator, boot rom exploit philanthropist , wild hacker , game developer,
RELATED ARTICLES

Most Popular

Recent Comments