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:
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.”