Mastering Jakarta JSON API from Java Applications

This tutorial will teach you how to use the Jakarta JSON Processing API from standalone Java applications. At the end of it, you will be able to create simple scripts in Java to manipulate, serialize and deserialize JSON content at scale.

Overview of Jakarta JSON Processing

Jakarta JSON Processing offers portable tools for parsing, generating, transforming, and querying JSON using two main approaches: Streaming API and Object Model API.

  • The Object Model API creates a tree-like structure in memory, allowing random access and queries. While flexible for complete data access, it’s less efficient than streaming, demanding more memory. This model navigates the entire tree for JSON generation.
  • The Streaming API enables parsing and generation of JSON in a streaming manner, granting the programmer control. It’s event-based, allowing developers to request the next event rather than handling it through callbacks, offering procedural control. Useful for local processing where random access isn’t needed, it allows event handling, discarding, and pulling the next event.

The purpose of this tutorial is to show how to use this API from a standalone Java application. To speed up the creation of scripts with Java, we will be using JBang which is the ideal wrapper for the execution of Java Classes. If you are new to JBang, please check this introduction article: JBang: Create Java scripts like a pro

First example: Let’s create JSON Objects

In the first example, we will show how to create a JSON Document fluently from our Java Class using the Jakarta JSON API. After that, we will extract and pretty-print the JSON file on the Console:

//usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS jakarta.json:jakarta.json-api:2.0.2
//DEPS org.glassfish:jakarta.json:2.0.1

import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.json.JsonWriter;
import jakarta.json.stream.JsonGenerator;

import java.io.StringWriter;
import java.util.Collections;

public class JSONPrettyFormat {
    public static void main(String[] args) {

        JsonObject jsonObject = Json.createObjectBuilder()
        .add("orderId", 12345678)
        .add("orderDate", "2023-10-04")
        .add("orderStatus", "Pending")
        .add("orderDetails", Json.createObjectBuilder()
                .add("shippingAddress", Json.createObjectBuilder()
                        .add("street", "123 Main Street")
                        .add("city", "Anytown")
                        .add("state", "CA")
                        .add("zipCode", "90210"))
        )
        .add("orderItems", Json.createArrayBuilder()
                .add(Json.createObjectBuilder()
                        .add("productId", 1002)
                        .add("productName", "Mouse")
                        .add("quantity", 1)
                        .add("unitPrice", 50))
        )
        .build();
    
        // Get the JSON string from the JSONObject
        // Create a StringWriter to store the formatted JSON
        StringWriter stringWriter = new StringWriter();

        // Create a JsonWriter with pretty printing (indentation) configuration
        JsonWriter jsonWriter = Json.createWriterFactory(
                Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true))
                .createWriter(stringWriter);

        // Write the JSON object with indentation to the StringWriter
        jsonWriter.writeObject(jsonObject);

        // Close the JsonWriter to release resources
        jsonWriter.close();

        // Get the formatted JSON string from the StringWriter
        String formattedJson = stringWriter.toString();

        // Print the formatted JSON
        System.out.println("Formatted JSON:");
        System.out.println(formattedJson);
    }
}

As you can see, to create a JSON Object we can use method chaining on top of the JSON object builder. The script generates a structured JSON object representing an order, including details like order ID, date, status, shipping information, and items.

The second part of the script utilizes Jakarta JSON APIs to create a well-formatted, human-readable JSON output by configuring a JsonWriter with pretty printing (indentation) settings.

In summary, to create a JSON Object, you need the following libraries on your Classpath:

  • The Jakarta JSON API ( jakarta.json:jakarta.json-api:2.0.2) which contains the API Contracts to use. You need this in order to compile your Java code
  • A Concrete implementation of the Jakarta JSON API (org.glassfish:jakarta.json:2.0.1). You will need this library at runtime. If your application is running in a Jakarta EE container, then it will provide for your this implementation.

By running the above script, will produce the following formatted JSON Output:

jakarta JSON tutorial

For more details on on how to pretty print JSON, check this article: Json pretty printing in Java

Second Example: From Java To JSON

In the second example, we will show how to serialize a Java Object ( to be precise a Java Record) into a JSON Object. Here is it:

//usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS jakarta.json.bind:jakarta.json.bind-api:3.0.0
//DEPS org.eclipse:yasson:3.0.3

//SOURCES Person.java

import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbException;

public class JavaToJSON {
    public static void main(String[] args) throws Exception {
        try {
            // Create a Person instance
            Person person = new Person(12345678, "John", "Smith", "[email protected]", "+1234567890");

            // Serialize Person record to JSON
            Jsonb jsonb = JsonbBuilder.create();
            String serializedJson = jsonb.toJson(person);
            System.out.println("Serialized JSON:");
            System.out.println(serializedJson);

            jsonb.close();
        } catch (JsonbException e) {
            e.printStackTrace();
        }
    }
}

The Java Record Person follows here:

public record Person(int customerId, String firstName, String lastName, String email, String phone) {
}

As you can see, in order to serialize a Java Object, you need the following libraries on your Classpath:

  • The Jakarta JSON Bind API ( jakarta.json:jakarta.json.bind-api:2.0.2) which enables binding Java objects from and to JSON documents. You need this in order to compile your Java code
  • A Concrete implementation of the Jakarta JSON Bind API (org.eclipse:yasson:3.0.3). You will need this library at runtime. If your application is running in a Jakarta EE container, then it will provide for your this implementation.

The resulting serialized JSON is then displayed, revealing the structured JSON object containing the person’s details. This demonstration highlights the simplicity and efficiency of the JSON-B API in marshalling Java Records into JSON format, a fundamental process for data interchange and persistence in modern applications:

{"customerId":12345678,"email":"[email protected]","firstName":"John","lastName":"Smith","phone":"+1234567890"}

Finally, please note that for basic cases like this, where the Record fields align with the desired JSON structure, JSON-B can handle serialization and deserialization without explicit annotations (such as @JsonbProperty )

Third Example: From JSON to Java

The third example we will show here will deserialize a JSON String into a Person Record Object. For this purpose, you can include the same dependencies of the serialization example:

//usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS jakarta.json.bind:jakarta.json.bind-api:3.0.0
//DEPS org.eclipse:yasson:3.0.3

//SOURCES Person.java
 
import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbException;
 
public class JSONToJava { 

    public static void main(String[] args) throws Exception {
      
        String jsonString = """
                {
                    "customerId": 12345678,
                    "firstName": "John",
                    "lastName": "Smith",
                    "email": "[email protected]",
                    "phone": "+1234567890"
                }
                """;

        // Deserialize JSON to Person record
        try {
            Jsonb jsonb = JsonbBuilder.create();

            Person person = jsonb.fromJson(jsonString, Person.class);

            // Accessing record fields
            System.out.println("Customer ID: " + person.customerId());
            System.out.println("First Name: " + person.firstName());
            System.out.println("Last Name: " + person.lastName());
            System.out.println("Email: " + person.email());
            System.out.println("Phone: " + person.phone());


            jsonb.close();
        } catch (JsonbException e) {
            e.printStackTrace();
        }
    }
}

The main difference is that we will be using the jakarta.json.bind.Jsonb interface to deserialize the JSON content into the Person type:

Person person = jsonb.fromJson(jsonString, Person.class);

By running it, you will see the Record properties printed on the Console:

Customer ID: 12345678
First Name: John
Last Name: Smith
Email: [email protected]
Phone: +1234567890

Conclusion

In summary, Jakarta JSON API’s user-friendly nature extends seamlessly to plain Java applications. When paired with JBang, its simplicity expedites JSON handling. This powerful combination empowers developers to efficiently manage JSON tasks, from basic object serialization to intricate data structures, simplifying Java applications with ease.”

Found the article helpful? if so please follow us on Socials