Guide to JsonPath Library in Java

Introduction to JsonPath

JsonPath is a powerful library for querying and extracting data from JSON documents. It provides a simple and flexible way to navigate through complex and nested JSON structures. Similar to XPath for XML, JsonPath allows you to specify a path to access various elements and attributes within a JSON document.

Installation

Adding JsonPath to Your Project

To use JsonPath, add the following dependency to your pom.xml if you're using Maven:

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

For Gradle:

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

Basic

Basic Usage

Parsing JSON

You can parse JSON strings into JsonPath objects for querying.

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;

public class JsonPathExample {
    public static void main(String[] args) {
        String json = "{ \"firstName\": \"Amit\", \"lastName\": \"Sharma\", \"age\": 30 }";
        ReadContext ctx = JsonPath.parse(json);

        String firstName = ctx.read("$.firstName");
        String lastName = ctx.read("$.lastName");
        int age = ctx.read("$.age");

        System.out.println("First Name: " + firstName);
        System.out.println("Last Name: " + lastName);
        System.out.println("Age: " + age);
    }
}

Output

First Name: Amit
Last Name: Sharma
Age: 30

Explanation: This example demonstrates basic parsing and querying of a JSON string using JsonPath. The $.firstName, $.lastName, and $.age paths are used to extract values from the JSON document.

Advanced Features

Extracting Nested JSON Objects

JsonPath can extract nested JSON objects and arrays.

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;

public class JsonPathNestedExample {
    public static void main(String[] args) {
        String json = "{ \"name\": \"Vikas\", \"address\": { \"street\": \"MG Road\", \"city\": \"Bangalore\" }, \"age\": 28 }";
        ReadContext ctx = JsonPath.parse(json);

        String street = ctx.read("$.address.street");
        String city = ctx.read("$.address.city");
        int age = ctx.read("$.age");

        System.out.println("Street: " + street);
        System.out.println("City: " + city);
        System.out.println("Age: " + age);
    }
}

Output

Street: MG Road
City: Bangalore
Age: 28

Explanation: This example demonstrates extracting nested JSON objects. The $.address.street and $.address.city paths are used to access nested properties within the address object.

Filtering JSON Arrays

JsonPath supports filtering JSON arrays based on certain conditions.

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;

import java.util.List;

public class JsonPathFilterExample {
    public static void main(String[] args) {
        String json = "{ \"students\": [ { \"name\": \"Priya\", \"marks\": 85 }, { \"name\": \"Rahul\", \"marks\": 75 }, { \"name\": \"Sneha\", \"marks\": 90 } ] }";
        ReadContext ctx = JsonPath.parse(json);

        List<String> topStudents = ctx.read("$.students[?(@.marks > 80)].name");

        System.out.println("Top Students: " + topStudents);
    }
}

Output

Top Students: [Priya, Sneha]

Explanation: This example demonstrates filtering JSON arrays. The $.students[?(@.marks > 80)].name path is used to filter and extract the names of students with marks greater than 80.

Using Wildcards

JsonPath supports wildcards to select multiple elements.

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;

import java.util.List;

public class JsonPathWildcardExample {
    public static void main(String[] args) {
        String json = "{ \"students\": [ { \"name\": \"Priya\", \"marks\": 85 }, { \"name\": \"Rahul\", \"marks\": 75 }, { \"name\": \"Sneha\", \"marks\": 90 } ] }";
        ReadContext ctx = JsonPath.parse(json);

        List<String> allNames = ctx.read("$.students[*].name");

        System.out.println("All Student Names: " + allNames);
    }
}

Output

All Student Names: [Priya, Rahul, Sneha]

Explanation: This example demonstrates using wildcards to select multiple elements. The $.students[*].name path selects the name property of all elements in the students array.

Modifying JSON

JsonPath can be used to modify JSON documents.

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.DocumentContext;

public class JsonPathModifyExample {
    public static void main(String[] args) {
        String json = "{ \"firstName\": \"Amit\", \"lastName\": \"Sharma\", \"age\": 30 }";
        DocumentContext ctx = JsonPath.parse(json);

        ctx.set("$.age", 31);
        ctx.put("$", "address", "Delhi");

        String modifiedJson = ctx.jsonString();

        System.out.println("Modified JSON: " + modifiedJson);
    }
}

Output

Modified JSON: {"firstName":"Amit","lastName":"Sharma","age":31,"address":"Delhi"}

Explanation: This example demonstrates modifying JSON documents. The set method is used to update the age property, and the put method is used to add a new address property.

Parsing JSON from a File

JsonPath can parse JSON from a file.

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;

import java.io.File;
import java.io.IOException;

public class JsonPathFileExample {
    public static void main(String[] args) throws IOException {
        File jsonFile = new File("student.json");
        ReadContext ctx = JsonPath.parse(jsonFile);

        String firstName = ctx.read("$.firstName");
        String lastName = ctx.read("$.lastName");
        int age = ctx.read("$.age");

        System.out.println("First Name: " + firstName);
        System.out.println("Last Name: " + lastName);
        System.out.println("Age: " + age);
    }
}

Explanation: This example demonstrates parsing JSON from a file using JsonPath. The parse method reads the JSON file and the read method extracts the values.

Predicates

Predicates in JsonPath are used to filter data based on conditions. They allow for complex filtering and conditional logic within queries.

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Predicate;

import java.util.List;

public class JsonPathPredicateExample {
    public static void main(String[] args) {
        String json = "{ \"students\": [ { \"name\": \"Priya\", \"marks\": 85 }, { \"name\": \"Rahul\", \"marks\": 75 }, { \"name\": \"Sneha\", \"marks\": 90 } ] }";
        Predicate highMarks = context -> context.read("$.marks", Integer.class) > 80;

        List<String> topStudents = JsonPath.parse(json).read("$.students[?]", List.class, highMarks);

        System.out.println("Top Students: " + topStudents);
    }
}

Output

Top Students: [{name=Priya, marks=85}, {name=Sneha, marks=90}]

Explanation: This example demonstrates using a predicate to filter students with marks greater than 80. The Predicate interface is implemented to define the filtering logic.

Operators

JsonPath supports various operators for querying and filtering JSON data, including logical, relational, and arithmetic operators.

Logical Operators

  • && - Logical AND
  • || - Logical OR

Relational Operators

  • == - Equal to
  • != - Not equal to
  • < - Less than
  • <= - Less than or equal to
  • > - Greater than
  • >= - Greater than or equal to

Example

import com.jayway.jsonpath.JsonPath;

import java.util.List;

public class JsonPathOperatorsExample {
    public static void main(String[] args) {
        String json = "{ \"students\": [ { \"name\": \"Priya\", \"marks\": 85 }, { \"name\": \"Rahul\", \"marks\": 75 }, { \"name\": \"Sneha\", \"marks\": 90 } ] }";
        List<String> topStudents = JsonPath.parse(json).read("$.students[?(@.marks > 80 && @.name == 'Priya')].name");

        System.out.println("Top Students: " + topStudents);
    }
}

Output

Top Students: [Priya]

Explanation: This example demonstrates using logical and relational operators to filter students with marks greater than 80 and whose name is "Priya".

Functions

JsonPath supports several built-in functions to perform operations on JSON data.

Length Function

The length() function returns the number of elements in an array or the number of properties in an object.

Example

import com.jayway.jsonpath.JsonPath;

public class JsonPathFunctionsExample {
    public static void main(String[] args) {
        String json = "{ \"students\": [ { \"name\": \"Priya\", \"marks\": 85 }, { \"name\": \"Rahul\", \"marks\": 75 }, { \"name\": \"Sneha\", \"marks\": 90 } ] }";
        int studentCount = JsonPath.parse(json).read("$.students.length()");

        System.out.println("Number of Students: "

 + studentCount);
    }
}

Output

Number of Students: 3

Explanation: This example demonstrates using the length() function to get the number of students in the JSON array.

Filters

Filters in JsonPath provide a way to perform advanced querying and filtering based on custom criteria.

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.Criteria;

import java.util.List;

public class JsonPathFiltersExample {
    public static void main(String[] args) {
        String json = "{ \"students\": [ { \"name\": \"Priya\", \"marks\": 85 }, { \"name\": \"Rahul\", \"marks\": 75 }, { \"name\": \"Sneha\", \"marks\": 90 } ] }";
        Filter filter = Filter.filter(Criteria.where("marks").gt(80).and("name").eq("Sneha"));

        List<String> filteredStudents = JsonPath.parse(json).read("$.students[?]", List.class, filter);

        System.out.println("Filtered Students: " + filteredStudents);
    }
}

Output

Filtered Students: [{name=Sneha, marks=90}]

Explanation: This example demonstrates using filters to query students with marks greater than 80 and whose name is "Sneha". The Filter and Criteria classes are used to define the filtering logic.

Complex and Nested Examples

Complex JSON Structure

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;

import java.util.List;

public class JsonPathComplexExample {
    public static void main(String[] args) {
        String json = "{ \"company\": { \"name\": \"Tech Solutions\", \"employees\": [ { \"name\": \"Vikas\", \"department\": \"Development\", \"skills\": [ \"Java\", \"Spring\", \"Hibernate\" ], \"experience\": 5 }, { \"name\": \"Priya\", \"department\": \"QA\", \"skills\": [ \"Selenium\", \"TestNG\", \"JUnit\" ], \"experience\": 3 }, { \"name\": \"Sneha\", \"department\": \"Development\", \"skills\": [ \"JavaScript\", \"React\", \"Node.js\" ], \"experience\": 4 } ] } }";
        ReadContext ctx = JsonPath.parse(json);

        String companyName = ctx.read("$.company.name");
        List<String> employeeNames = ctx.read("$.company.employees[*].name");
        List<String> priyaSkills = ctx.read("$.company.employees[?(@.name == 'Priya')].skills[*]");

        System.out.println("Company Name: " + companyName);
        System.out.println("Employee Names: " + employeeNames);
        System.out.println("Priya's Skills: " + priyaSkills);
    }
}

Output

Company Name: Tech Solutions
Employee Names: [Vikas, Priya, Sneha]
Priya's Skills: [Selenium, TestNG, JUnit]

Explanation: This example demonstrates querying a complex JSON structure. The paths $.company.name, $.company.employees[*].name, and $.company.employees[?(@.name == 'Priya')].skills[*] are used to extract various elements from the JSON document.

Nested JSON Arrays

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.ReadContext;

import java.util.List;

public class JsonPathNestedArraysExample {
    public static void main(String[] args) {
        String json = "{ \"university\": { \"name\": \"Delhi University\", \"departments\": [ { \"name\": \"Computer Science\", \"courses\": [ { \"name\": \"Data Structures\", \"code\": \"CS101\" }, { \"name\": \"Algorithms\", \"code\": \"CS102\" } ] }, { \"name\": \"Mathematics\", \"courses\": [ { \"name\": \"Calculus\", \"code\": \"MATH101\" }, { \"name\": \"Linear Algebra\", \"code\": \"MATH102\" } ] } ] } }";
        ReadContext ctx = JsonPath.parse(json);

        String universityName = ctx.read("$.university.name");
        List<String> departmentNames = ctx.read("$.university.departments[*].name");
        List<String> courseNames = ctx.read("$.university.departments[*].courses[*].name");

        System.out.println("University Name: " + universityName);
        System.out.println("Department Names: " + departmentNames);
        System.out.println("Course Names: " + courseNames);
    }
}

Output

University Name: Delhi University
Department Names: [Computer Science, Mathematics]
Course Names: [Data Structures, Algorithms, Calculus, Linear Algebra]

Explanation: This example demonstrates querying nested JSON arrays. The paths $.university.name, $.university.departments[*].name, and $.university.departments[*].courses[*].name are used to extract values from nested arrays.

Combining Predicates, Operators, Functions, and Filters

Example

import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Predicate;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.Criteria;

import java.util.List;

public class JsonPathAdvancedExample {
    public static void main(String[] args) {
        String json = "{ \"company\": { \"name\": \"Tech Solutions\", \"employees\": [ { \"name\": \"Vikas\", \"department\": \"Development\", \"skills\": [ \"Java\", \"Spring\", \"Hibernate\" ], \"experience\": 5 }, { \"name\": \"Priya\", \"department\": \"QA\", \"skills\": [ \"Selenium\", \"TestNG\", \"JUnit\" ], \"experience\": 3 }, { \"name\": \"Sneha\", \"department\": \"Development\", \"skills\": [ \"JavaScript\", \"React\", \"Node.js\" ], \"experience\": 4 } ] } }";

        Predicate highExperience = context -> context.read("$.experience", Integer.class) > 3;
        Filter developmentFilter = Filter.filter(Criteria.where("department").is("Development"));

        List<String> experiencedDevelopers = JsonPath.parse(json).read("$.company.employees[?]", List.class, highExperience.and(developmentFilter));

        System.out.println("Experienced Developers: " + experiencedDevelopers);
    }
}

Output

Experienced Developers: [{name=Vikas, department=Development, skills=[Java, Spring, Hibernate], experience=5}, {name=Sneha, department=Development, skills=[JavaScript, React, Node.js], experience=4}]

Explanation: This example demonstrates combining predicates, operators, functions, and filters to query employees with experience greater than 3 years and who are in the Development department. The Predicate and Filter classes are used to define the filtering logic.

Conclusion

JsonPath is a powerful and flexible library for querying and extracting data from JSON documents in Java. This guide covered the basics of JsonPath, including parsing JSON, extracting nested objects, filtering arrays, using wildcards, modifying JSON, and parsing JSON from files. It also explored advanced features like predicates, operators, functions, and filters, along with complex examples. By leveraging JsonPath, you can efficiently navigate and manipulate JSON structures in your Java applications. For more detailed information and advanced features, refer to the official JsonPath documentation.

Comments