Introduction

Working with JSON data is a common task for Java developers.
With the Jayway JsonPath library, navigating, querying, and manipulating JSON data becomes much easier and more efficient.
In this comprehensive guide, we will walk you through the setup, notation, sample JSON, operators, functions, filters, operations, predicates, and various options available with Jayway JsonPath.
Whether you’re a beginner or an experienced Java developer, understanding how to effectively use Jayway JsonPath can greatly streamline your JSON data processing workflows.

Environment Setp

Setting up JsonPath is very easy. You simply need to add dependency as per the build tool below

<!-- MAVEN -->
<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.9.0</version>
</dependency>

// GRADLE
implementation 'com.jayway.jsonpath:json-path:2.9.0'

JsonPath Basics

To effectively work with JSON data in Java, understanding JsonPath is essential.
JsonPath is a powerful tool that allows you to query and manipulate JSON structures with ease.
In this article, we will probe into the basics of JsonPath and explore its syntax, key components, and types of operations.

JsonPath Syntax

Basics of JsonPath involve learning its unique syntax for navigating JSON structures.
JsonPath uses a simple dot notation to access elements within the JSON data.
For example, ‘$.store.book[0].title’ represents the path to the title of the first book in the store.
By understanding and mastering the syntax, you can efficiently extract specific values from complex JSON data.

Sample JSON

Below is a sample JSON, which we will be using to query nodes and extract values.

{
  "university": "ABC University",
  "students": [
    {
      "id": 1,
      "name": "John Doe",
      "age": 20,
      "major": "Computer Science",
      "courses": ["Introduction to Programming", "Data Structures", "Algorithms"]
    },
    {
      "id": 2,
      "name": "Jane Smith",
      "age": 21,
      "major": "Electrical Engineering",
      "courses": ["Circuit Analysis", "Digital Logic", "Control Systems"]
    }
  ],
  "professors": [
    {
      "id": 101,
      "name": "Dr. Robert Johnson",
      "department": "Computer Science",
      "courses_taught": ["Introduction to Programming", "Data Structures", "Algorithms"]
    },
    {
      "id": 102,
      "name": "Dr. Emily Davis",
      "department": "Electrical Engineering",
      "courses_taught": ["Circuit Analysis", "Digital Logic", "Control Systems"]
    }
  ]
}

In this JSON structure, there’s a university with information about its students and professors.
Each student has an ID, name, age, major, and an array of courses they are enrolled in.
Similarly, each professor has an ID, name, department, and an array of courses they teach.

Parsing JSON

To parse a JSON string into an object with JsonPath, you can use com.jayway.jsonpath.JsonPath class and its static method parse(), which accepts a JSON string as shown below

// JSON string
String jsonStr = "{\"university\":\"ABC University\"," +
              "\"students\":" +
	      "[" +
		 "{\"id\":1,\"name\":\"John Doe\",\"age\":20,\"major\":\"Computer Science\"}," +
	         "{\"id\":2,\"name\":\"Jane Smith\",\"age\":21,\"major\":\"Electrical Engineering\"} +
               "]," +
	       "\"professors\":" +
		"[" +
		 "{\"id\":101,\"name\":\"Dr. Robert Johnson\",\"department\":\"Computer 
                   Science\",\"courses_taught\":[\"Introduction to Programming\",\"Data 
                   Structures\",\"Algorithms\"]}," +
		"{\"id\":102,\"name\":\"Dr. Emily Davis\",\"department\":\"Electrical 
                 Engineering\",\"courses_taught\":[\"Circuit Analysis\",\"Digital Logic\",\"Control Systems\"]}" +
		"]}";
DocumentContext doc = JsonPath.parse(jsonStr);

Navigating JSON with JsonPath

JsonPath is a powerful tool that allows you to query and extract specific data from JSON documents with ease.
By mastering the art of JsonPath, you can efficiently navigate through complex JSON structures and retrieve the data you need.

Selecting Nodes in JSON

With JsonPath, you can select nodes in JSON by specifying the path to the desired elements using dot notation.
In JsonPath, $ represents the document root and to select a node, it needs to be followed by dot notation.
For selecting node, we need to create an expression to reach that node according to the JSON structure.

Once we are ready with the expression, we need to pass it to the read() method which is called on DocumentContext that we get by parse() method in the last section.
So, in above example, if we need to get the value of university node, then we can do it as

DocumentContext doc = JsonPath.parse(jsonString);
String jsonPathExpression = "$.university";
Object result = doc.read(jsonPathExpression);
System.out.println(result); // prints ABC University

Instead of dot, you can also use square brackets([ and ]) containing the name of key enclosed between single quotes as below

DocumentContext doc = JsonPath.parse(json);
String jsonPathExpression = "$['university']";
Object result = doc.read(jsonPathExpression);
System.out.println(result); // prints ABC University

Accessing nested nodes

Suppose, we have a JSON structure as

{ 
  "employee": {
      "name":"Abc",
       "id":1
  }
}

And you want to select its id, which is inside employee object.
This is called nested keys.

With JsonPath, once you select a node, you can refer to its child nodes by using dot operator as below

String jsonPathExpression = "$.employee.id";
Object result = JsonPath.parse(json).read(jsonPathExpression);
System.out.println(result);

Accessing JSON array elements

Suppose you have an array in JSON and you want to get a particular element, then it can be done by selecting the array using its key and then that particular element using its index enclosed between [ and ].
Array index starts at 0, similar to java arrays.

For example, to select the first student from the array of students in above JSON string, below code can be used

String jsonPathExpression = "$.students[0]";
Object result = JsonPath.parse(json).read(jsonPathExpression);
System.out.println(result);

Following will be the output

{“id”: 1,”name”: “John Doe”,”age”: 20,”major”: “Computer Science”,”courses”: [“Introduction to Programming”, “Data Structures”, “Algorithms”]}

And to further select a node in this array element, we can reference it with corresponding key in path expression.
Below code selects the name of first student in students array.

String jsonPathExpression = "$.students[0].name";
Object result = JsonPath.parse(json).read(jsonPathExpression);
System.out.println(result); // John Doe

Referring Current Node

In JsonPath, the current node is referred using @ symbol, which is called current node or current context symbol.
It indicates the current element being evaluated during traversal of the JSON structure.
It allows for dynamic referencing of elements within arrays or objects being processed.

@ is mainly used for below purposes

  1. Filtering Arrays
    When applying filters to arrays, @ refers to the current array element being evaluated.
    For example, in the JsonPath expression $.students[?(@.age > 20)], @ refers to each individual student object within the students array.
  2. Filtering Objects
    When applying filters to objects, @ can also be used to refer to the current object being evaluated.
    For example, in the JsonPath expression $..book[?(@.price < 10)], @ refers to each individual book object within the JSON structure.
  3. Functions
    @ can also be used with functions to refer to the current context.
    For example, @.length() can be used to get the length of an array.

Filtering

Filters in JsonPath allow you to further refine the selection of elements from your JSON based on certain conditions.

Filters are specified within square brackets [ ], along with the condition with ?().
Each node is referred with @ symbol.

Here’s a basic overview of how filters work in JsonPath:

  • The syntax for a filter in JsonPath is ?[condition].
  • The condition can be any valid expression that evaluates to a boolean value.
  • Elements that satisfy the condition are included in the result, while those that don’t are excluded.

Let’s consider an example JSON structure representing a list of products

{
  "products": [
    {
      "name": "Laptop",
      "price": 999,
      "brand": "Dell"
    },
    {
      "name": "Smartphone",
      "price": 699,
      "brand": "Samsung"
    },
    {
      "name": "Tablet",
      "price": 299,
      "brand": "Apple"
    }
  ]
}

Suppose we want to select only those products whose price is greater than or equal to $500. We can use a filter for this purpose.
Here’s how you can do it using JsonPath

import com.jayway.jsonpath.JsonPath;

public class JsonPathExample {
    public static void main(String[] args) {
        String jsonStr = "{\"products\":" +
                          "[" + 
                          "{\"name\":\"Laptop\",\"price\":999,\"brand\":\"Dell\"}," + 
                          "{\"name\":\"Smartphone\",\"price\":699,\"brand\":\"Samsung\"}," + 
                          "{\"name\":\"Tablet\",\"price\":299,\"brand\":\"Apple\"}]}";
        // Applying filter with JsonPath
        String jsonPathExpression = "$.products[?(@.price >= 500)]";
        Object result = JsonPath.parse(jsonStr).read(jsonPathExpression);

        System.out.println(result);
    }
}

In this example, the JsonPath expression $.products[?(@.price >= 500)] filters out only those products whose price is greater than or equal to $500.
When applied to the given JSON, it will return

[
  {
    "name": "Laptop",
    "price": 999,
    "brand": "Dell"
  },
  {
    "name": "Smartphone",
    "price": 699,
    "brand": "Samsung"
  }
]

Similarly, you can apply filters to get objects based on equality(==).

Matching nodes with value

Suppose you want to get objects whose brand is Samsung.

Below code would be used for that

String jsonStr = "{\"products\":" + "[" + "{\"name\":\"Laptop\",\"price\":999,\"brand\":\"Dell\"},"
				+ "{\"name\":\"Smartphone\",\"price\":699,\"brand\":\"Samsung\"},"
				+ "{\"name\":\"TV\",\"price\":699,\"brand\":\"Samsung\"},"
				+ "{\"name\":\"Tablet\",\"price\":299,\"brand\":\"Apple\"}]}";
// Applying filter with JsonPath
String jsonPathExpression = "$.products[?(@['brand']=='Samsung')]";
Object result = JsonPath.parse(jsonStr).read(jsonPathExpression);

Find value in list

Suppose you have an array of JSON object and you want to find objects whose some key has a specific value.

Consider JSON string below

{
  "products": [
    {"name": "Laptop", "category": "Electronics"},
    {"name": "Smartphone", "category": "Electronics"},
    {"name": "Book", "category": "Books"},
    {"name": "Headphones", "category": "Electronics"}
  ]
}

Suppose we want to find all products that belong to either the Electronics or Books category.

We can use the in operator to achieve this.

In JsonPath, the in operator is used to check if a value is present in a given list of values.
It allows you to filter elements based on whether a certain property’s value matches any of the values in the specified list.
Here’s how you can use the in operator to achieve this

import com.jayway.jsonpath.JsonPath;

public class JsonPathExample {
    public static void main(String[] args) {
      String json = "{\"products\":[{\"name\":\"Laptop\",\"category\":\"Electronics\"}," +
                     "{\"name\":\"Smartphone\",\"category\":\"Electronics\"}," + 
                     "{\"name\":\"Book\",\"category\":\"Books\"}," + 
                     "{\"name\":\"Headphones\",\"category\":\"Electronics\"}" + 
                     "]}";
    // Using the in operator with JsonPath
    String jsonPathExpression = "$.products[?(@.category in ['Electronics', 'Books'])]";
    Object result = JsonPath.parse(json).read(jsonPathExpression);
    System.out.println(result);
  }
}

In this example, the JsonPath expression $.products[?(@.category in ['Electronics', 'Books'])] selects all products where the category property is either Electronics or Books.
The in operator checks if the value of the “category” property is present in the specified list of values.

Note that @ refers to the current node and is checked for each node.

Functions

JsonPath supports various functions that allow for more complex querying and manipulation of JSON data.

A commonly used function is the length() function, which returns the length of an array.
Here’s an example demonstrating the use of length() function in JsonPath.

import com.jayway.jsonpath.JsonPath;

public class JsonPathExample {
  public static void main(String[] args) {
    String json = "{\"students\":" + 
                  "[" + 
                   "{\"name\":\"John\",\"grades\":[85,90,95]}," + 
                   "{\"name\":\"Alice\",\"grades\":[75,80,85,90]}," + 
                   "{\"name\":\"Bob\",\"grades\":[70,75]}" + 
                  "]}";
    // Using the length() function with JsonPath
    String jsonPathExpression = "$.students[?(@.grades.length() > 3)]";
    Object result = JsonPath.parse(json).read(jsonPathExpression);
    System.out.println(result);
  }
}

In this example, the JsonPath expression $.students[?(@.grades.length() > 3)] selects all students whose “grades” array has a length greater than 3.
The length() function is called on the grades array within each student object to determine its length.
When applied to the given JSON, it will return

[
  {"name": "Alice", "grades": [75, 80, 85, 90]}
]

Conclusion

From the above comprehensive guide to Jayway JsonPath with code examples, it is clear that understanding and utilizing this library in Java can greatly enhance JSON parsing capabilities.

By understanding the setup, notation, sample JSON, operators, functions, filters, operations, and predicates associated with JsonPath, developers can harness the power of this tool to efficiently extract and manipulate data from JSON structures.