JSON-P Tutorial – Process JSON data structures

Last Updated:  May 13, 2020 | Published: September 26, 2019

Besides binding and converting JSON from an to Java objects with JSON-B, the Java EE specification (now Jakarta EE) offers a specification to process JSON data: JSON Processing (JSON-P). With this spec, you can easily create, write, read, stream, transform and query JSON objects. This specification is also part of the Eclipse MicroProfile project and provides a simple API to handle and further process JSON data structures as you'll see it in the following examples.

Learn more about the JSON Processing (JSON-P) specification and how to use it in this blog post.

Specification profile: JSON Processing (JSON-P)

  • Current version: 1.1
  • GitHub repository
  • Specification homepage
  • Basic use case: Process JSON messages (parse, generate, transform and query)

Construct JSON objects using JSON-P

With JSON-P you can easily build JSON objects on-demand. You can create a JsonObjectBuilder using the Json class and build the JSON object while adding new attributes to the object:

If you print this object, you already have a valid JSON and can return this e.g. from a JAX-RS endpoint or use it as an HTTP request body:

You are not limited to create JSON objects only, you can also request for a JsonArrayBuilder and start constructing your JSON array:

Write JSON objects

Given a JSON object, you can also write it to a different source using JSON-P and its JsonWriterFactory. As an example, I'm writing a JSON object to a File in pretty-print:

The JsonWriterFactory accepts any Writer or OutputStream to instantiate the JsonWriter:

Using the JSON object from the chapter above, the output on the console will look like the following:

Read JSON with the JSON-P specification

The specification also provides a convenient way to read and parse JSON from a given source (e.g. File or String). To create a JsonReader instance, you either have to provide a InputStream or a Reader. As an example, I'm reading from both a String and a File on the classpath:

If the JSON is not valid, the JsonReader throws a JsonParsingExcpetion while parsing it and will give a hint about what is wrong e.g. Invalid token=SQUARECLOSE at (line no=1, column no=54, offset=53). Expected tokens are: [COLON].

Stream JSON data

For use cases where you have to process big JSON objects (which might not fit into memory), you should have a look at the streaming options of JSON-P. The specification says the following about its streaming capabilities:

Unlike the Object model this offers more generic access to JSON strings that may change more often with attributes added or similar structural changes. Streaming API is also the preferred method for very large JSON strings that could take more memory reading them altogether through the Object model API.

Streaming works for both parsing and generating JSON objects. To parse and process a big JSON object, the spec provides the JsonParser:

This offers rather low-level access to the JSON object and you can access all Event objects (e.g. START_ARRAY, KEY_NAME, VALUE_STRING) while parsing.

For creating a JSON object in a streaming-fashion, you can use the JsonGenerator class and write to any source using a Writer or OutputStream:

Transform JSON with JsonPointer, JsonPatch and JsonMergePatch

Since JSON-P 1.1, the specification offers a great way to query and transform JSON structures using the following standardized JSON operations:

Identify a specific value with JSON Pointer

If your JSON object contains several sub-objects and arrays and you have to find the value of a specific attribute, iterating over the whole object is cumbersome. With JSON Pointer you can specify an expression and point to a specific attribute and directly access it. The expression is defined in the official RFC.

Once you have a JSON pointer in place, you can get the value, remove it, replace it, add a new and check for existence with JSON-P and its JsonPointer class:

Define a sequence of operations to apply using JSON Patch

Similar to the JSON Pointer in the example above, you can define a set of operations to apply on a given JSON with JSON Patch. The possible operations to apply to a JSON are defined in the official RFC. As an example, I'm modifying an existing JSON with JsonPatch like the following:

The patched JSON object looks like the following:

Merge two JSON objects with JSON Merge Patch

If you want to merge a given JSON object with another JSON, you can make use of the JSON Merge Patch. With this, you first have to define how the merge JSON object looks like and can then apply it to a target JSON structure.

The merged JSON in this example looks like the following:

For more information about the JSON Merge Patch, have a look at the official RFC.

YouTube video for using JSON-P 1.1 specification

Watch the following YouTube video of my Getting started with Eclipse MicroProfile series to see JSON-P 1.1 in action:

You can find the source code with further instructions to run this example on GitHub.

Have fun using the JSON-P specification,

Phil

>