Extracting JSON using JsonPath with Examples

Learn to extract information from JSON documents using Jayway’s JsonPath. JsonPath is similar to Xpath for XML documents. This tutorial will go through the JsonPath syntax and a few examples to better understand its usage.

1. Setting Up JsonPath

Include the JsonPath to the application if not added already. We can find the latest version of JsonPath in Maven repository.

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.7.0</version>
</dependency>

Normally, we will get the JSON document from an API response or any other source in an application. But, in this example, we are reading a JSON file.

{
  "widget": {
    "debug": "on",
    "window": {
      "title": "Client Info",
      "name": "client_info",
      "width": 500,
      "height": 500,
      "padding": [10,10,10,50],
      "locations" : [
        { "name": "header", "display": "true" },
        { "name": "footer", "display": "true" },
        { "name": "sidebar", "display": "false" }
      ]
    }
  }
}

If we are writing a Junit test, we can read the JSON to a String in setup() method.

static String json;

@BeforeAll
public static void setup() {
  try {
    URL fileUrl = TestJsonPathExpressions.class.getClassLoader().getResource("widget.json");
    File file = new File(fileUrl.getFile());
    json = new String(Files.readAllBytes(file.toPath()));
  } catch (Exception e) {
    e.printStackTrace();
  }
}

2. A Simple Example

Before digging deep into syntax, let us start with a simple example of how to extract the information from the given document. In the following example, we extract the widget title name and verify the expected value.

@Test
public void testGetWidgetTitle_ThenSuccess(){

  String widgetTitle = JsonPath.read(json, "$.widget.window.title");
  Assertions.assertEquals("Client Info", widgetTitle);
}

3. JsonPath Syntax

3.1. Notations

JsonPath support two notations to represent nodes: dot and bracket. In the following example, both expressions point to the same node:

  • $.widget.window.title //Dot notation
  • $['widget']['window']['title'] //Bracket notation

3.2. Operators

JsonPath supports many operators that can be used to represent specific nodes or ranges within the JSON document.

  • $ represents the root node. All path expressions start with it.
  • @ represents the current node being processed. It is used with a filter predicate. In following example, we are finding all the locations where display is true.
@Test
public void testGetDisplayLocations_ThenSuccess(){

  List<String> locations = JsonPath.read(json, "$.widget.window.locations[?(@.display == 'true')].name");
  Assertions.assertTrue(List.of("header", "footer").containsAll(locations));
}
  • * represents all the nodes in the current scope. For example, following expression returns all locations irrespective of the display property.
@Test
public void testGetAllDisplayLocations_ThenSuccess(){

  List<String> locations = JsonPath.read(json, "$.widget.window.locations[*].name");
  Assertions.assertTrue(List.of("header", "footer", "sidebar").containsAll(locations));
}
  • [start:end] slices the elements of an array from start to end indices.
@Test
public void testFirstDisplayLocation_ThenSuccess(){

  List<String> locations = JsonPath.read(json, "$.widget.window.locations[0,1].name");
  Assertions.assertTrue(List.of("header", "footer").containsAll(locations));
}

3.3. Functions

JsonPath provides inbuilt functions to support some common operations such as: sum(), min(), max(), avg(), stddev(), length(), keys(), concat(input) and append(input).

In the following example, we are finding the largest padding values for the widget.

@Test
public void testLargestPadding_ThenSuccess(){

  Double largestPadding = JsonPath.read(json, "$.widget.window.padding.max()");
  Assertions.assertEquals(50, largestPadding);
}

4. JsonPath Predicates

Predicates help in filtering an array of nodes based on provided condition(s). This is useful when we want to extract only those array items that match a certain criterion.

We have already seen the inline predicate example in the previous section.

List<String> locations = JsonPath.read(json, "$.widget.window.locations[?(@.display == 'true')].name");

Let us rewrite the same predicate with com.jayway.jsonpath.Predicate class. Notice the use of ? character in ‘locations[?]’ that implied the location of the predicate to apply.

@Test
public void testGetTrueDisplayLocationsWithPredicate_ThenSuccess(){

  Predicate displayEnabled = new Predicate() {
    @Override
    public boolean apply(PredicateContext ctx) {
      return ctx.item(Map.class).get("display").toString().equalsIgnoreCase("true");
    }
  };

  List<String> locations = JsonPath.read(json, "$.widget.window.locations[?].name", displayEnabled);
  Assertions.assertTrue(List.of("header", "footer").containsAll(locations));
}

Note that we can pass multiple predicates and placeholders in an expression. When multiple predicates are provided they are applied in order where the number of placeholders must match the number of provided predicates. In the following example, we are passing two predicates widgetEnabled and displayEnabled.

JsonPath.read(json, "$.widget.window[?].locations[?].name", widgetEnabled, displayEnabled);

5. Custom Configurations

JsonPath Option enum provides several options to customize the default configuration:

  • Option.AS_PATH_LIST returns evaluation paths instead of the values.
  • Option.DEFAULT_PATH_LEAF_TO_NULL returns null for missing nodes.
  • Option.ALWAYS_RETURN_LIST returns a List even when the expression evaluates a single value.
  • Option.SUPPRESS_EXCEPTIONS suppresses all exceptions in runtime.
  • Option.REQUIRE_PROPERTIES requires properties defined in the path when an indefinite path is evaluated.

To pass the configuration to JsonPath object, use its using() method. In following example, we are fetching a single value, but it is being returned as a List.

@Test
public void testConfiguration_ThenSuccess(){

  Configuration configuration = Configuration
      .builder()
      .options(ALWAYS_RETURN_LIST, SUPPRESS_EXCEPTIONS)
      .build();

  List<String> locations = JsonPath
      .using(configuration)
      .parse(json).read("$.widget.window.locations[0].name");
  Assertions.assertTrue(List.of("header").containsAll(locations));
}

6. Conclusion

In this JsonPath Tutorial, we learned to set up and configure JsonPath according to our needs. We learned the JsonPath syntax including notations, symbols and operators with examples. We also went through a few examples of extracting information from JSON documents by applying filters using the predicates.

Happy Learning !!

Sourcecode on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode