How to use JSON-B for parsing Java objects to/from JSON

In this tutorial we will learn about JSON-B, which is a standard binding layer for converting Java objects to/from JSON messages, included as part of JSR 367 Specification (Java EE 8).

In general terms, there are two main APIs to handle JSON in Java:

  • JSON-P (JSON-Processing, JSR 374): Specifies a very low-level processing library which can be carried out with two models for JSON processing: the Object Model API and the Streaming API.
  • JSON-B (JSON-Binding, JSR 367): Provides a binding layer on top of JSON-P, making it easier to convert objects to and from JSON.

If you want an overview on both JSON API, we recommend checking this tutorial: How to parse JSON in Java

Getting started with JSON-B

JSON-B defines a default mapping API for converting existing Java classes to JSON and viceversa. It brings several advantages such as:

  • Consistency with JAXB (Java API for XML Binding) and other Java EE and SE APIs where appropriate
  • Standard for mapping of Java classes and instances to JSON document counterparts
  • Customizable: Allow customization of the default mapping definition
  • Ease of use: Default use of the APIs should not require prior knowledge of the JSON document format and specification

Let’s see a practical application on WildFly which has support for Java EE 8 in all its profiles:

$ ./standalone.sh 

And here is a simple REST Service which we will deploy as Web application:

package com.itbuzzpress.json.service;

import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;

import javax.ws.rs.FormParam;

import javax.ws.rs.POST;
import javax.ws.rs.Path;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.itbuzzpress.json.model.Person;

@Path("/jsonb")
public class JsonService {

	@POST
	@Path("/tojava")
	public Response createJava(@FormParam("json") String json) {
		Response response;

		Jsonb jsonb = JsonbBuilder.create();

		Person p = jsonb.fromJson(json, Person.class);
		System.out.println("Created Person " + p);
		response = Response.ok(p.toString()).build();

		return response;
	}

	@POST
	@Produces(MediaType.APPLICATION_JSON)
	@Path("/tojson")
	public Response createJson(@FormParam("name") String name, @FormParam("surname") String surname,
			@FormParam("address") String address, @FormParam("city") String city) {
		Response response;
		Person p = new Person(name, surname, address, city);

		Jsonb jsonb = JsonbBuilder.create();
		String jsonString = jsonb.toJson(p);
		response = Response.ok(jsonString).build();

		return response;
	}
}

This REST service contains two methods, the former createJava will create a Java Object from a Json String passed as Form parameter and output the toString() of the Java object as response.

The main class used in this example is javax.json.bind.Jsonb. This class provides all necessary methods to serialize and deserialize Java objects.

In the first method we use the static fromJson method to create a JSON from a Java Object

In the second method we instead use the toJson to do exactly the opposite, that is converting from a Java Object to a JSON String.

Please note that Jsonb instances are thread safe. They can be cached and reused.

A minimal JSP will be created as front-end for our application:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>Enter Properties for Person</h2>
	<form method="post" action="rest/jsonb/tojson">
		<label>Name</label><br /> <input type="text" name="name"><br />
		<label>Surname</label><br /> <input type="text" name="surname"><br />
		<label>Address</label><br /> <input type="text" name="address"><br />
		<label>City</label><br /> <input type="text" name="city"><br />
		<label> </label> <br /> <input type="submit" value="Create Json">
	</form>


	<br />
	<h2>Enter Json for Object "Person" here:</h2>
	<h3>Example: { "name": "John", "surname": "Doe", "address": "77 E
		4th St", "city": "New York" }</h3>
	<form method="post" action="rest/jsonb/tojava">
		Json<br /> <input type="text" name="json" width="400" /> <br> <br />
		<input type="submit" value="Create Java">
	</form>
</body>
</html>

Here is out application in action:

JSON-B tutorial java ee 8 jakarta ee wildfly jboss

The example is available on my repository https://github.com/fmarchioni/practical-javaee7-development-wildfly/tree/javaee8/code/chapter13/jsonbjavatojson and it will be included in Practical Java EE development I’m currently updating.

Mapping a collection

In the above example we have mapped a single Java object to Json, however JSON-B supports also collections and generic collections handling. It can be done a way shown below:

List<Person> list = new ArrayList<>();
Person p1 = new Person(name1, surname1, address1, city1);
Person p2 = new Person(name2, surname2, address2, city2);

list.add(p1);
list.add(p2);

Jsonb jsonb = JsonbBuilder.create();
String result = jsonb.toJson(list);

// Deserialize back
list = jsonb.fromJson(result, new ArrayList<Person>(){}.getClass().getGenericSuperclass());

Customized mapping

Json mappings can be customized in several ways. You can use JSON-B annotations for compile time customizations and JsonbConfig class for runtime customizations.

For example, the Person class can be customized using the @JsonbProperty to specify a custom naming policy:

public class Person {
    @JsonbProperty("first-name")
    private String name;

    .....
}

This would result in the following Json:

{"address":"77 E 4th St","city":"New York","first-name":"John","surname":"Doe"}

Among the other features, it is also possible the creation of custom configuration by skipping elements with null values such as in the following example:

// Create custom configuration
JsonbConfig nillableConfig = new JsonbConfig().withNullValues(true);

// Create Jsonb with custom configuration
Jsonb jsonb = JsonbBuilder.create(nillableConfig);

// Use it!
String result = jsonb.toJson(person);

Customized JSON Mapping

JSON Binding hands developers sophisticated control over the mapping of Java fields to Json. For this purpose you can create a custom JsonbConfig object with custom JSON mapping strategy. See the following example:

JsonbConfig jsonbConfig = new JsonbConfig()

    .withPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE_WITH_DASHES)
    .withPropertyOrderStrategy(PropertyOrderStrategy.LEXICOGRAPHICAL)
    .withStrictIJSON(true)
    .withFormatting(true)
    .withNullValues(true);

Jsonb jsonb = JsonbBuilder.create(jsonbConfig);

As far as the PropertyNamingStrategy is concerned, you have the following options:

  • IDENTITY: The name is unchanged (default strategy).     
  • LOWER_CASE_WITH_DASHES: The name is translated to lowercase with dashes delimiting differences in case.     
  • LOWER_CASE_WITH_UNDERSCORES: The name is translated to lowercase with underscores delimiting differences in case.     
  • UPPER_CAMEL_CASE: The first character is capitalized.     
  • UPPER_CAMEL_CASE_WITH_SPACES: The first character is capitalized with spaces delimiting differences in case.    
  • CASE_INSENSITIVE: The Identity strategy is used for serialization, but for deserialization the property name is insensitive to case.     

Then, as far as PropertyOrderStrategy is concerned, you can opt for:

  • LEXICOGRAPHICAL: Properties are ordered lexicographically (default strategy).
  • ANY: There is no guaranteed order to properties.
  • REVERSE: Properties are ordered reverse-lexicographically.

Handling Null values

By default JSON-B doesn’t serialize fields with null values. There are three different ways to change default null handling.

On a class or package level using @JsonbNillable annotation

@JsonbNillable
public class Person {
    private String name;
    private String profession;
}

On individual properties using @JsonbProperty annotation with nillable=true parameter

public class Person {
    @JsonbProperty(nillable=true)
    private String name;

    private String profession;
}

Globally using withNullValues method of JsonbConfig class

JsonbConfig nillableConfig = new JsonbConfig()
    .withNullValues(true);

Jsonb jsonb = JsonbBuilder.create(nillableConfig);
Found the article helpful? if so please follow us on Socials