JsonPath Example With Spring

Jayway JsonPath is an open-source implementation of JsonPath for Java. We can also use JsonPath to query and traverse through JSON data. Let’s explore more by creating an example spring application.

In this post, we will learn about the basic usage of the JasonPath Maven library.

We will also learn how to use it in our spring application.

Finally, we will create a simple spring boot application, and a few REST endpoints to retrieve the JSON data from the backend service.

Create a spring boot application

Create a spring boot application with spring-boot-starter-web, Lombok(to reduce boilerplate code), and the json-path dependencies.

The complete pom.xml file is given below.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.3.BUILD-SNAPSHOT</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.asb.example</groupId>
	<artifactId>spring-jsonpath-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-jsonpath-example</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>com.jayway.jsonpath</groupId>
			<artifactId>json-path</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

Create DTO classes

We will create a few simple DTO classes and relate them to form a nested JSON structure.

Create Java classes called School, Student, and Grade

School.java

package com.asb.example.dto;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class School {
	private String name;
	List<Student> students = new ArrayList<>();
}

Student.java

package com.asb.example.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Student {
	private String firstName;
	private String lastName;
	private Grade grade;
}

Grade.java

package com.asb.example.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Grade {
	private String name;
}

Creating the Service layer

Create a spring service class to create and return objects of the above created DTO classes.

Also, create a utility java class called JsonUtil as shown below.

Now, this utility class creates the Objects and returns them back to the service class.

JsonUtil.java

package com.asb.example.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import com.asb.example.dto.Grade;
import com.asb.example.dto.School;
import com.asb.example.dto.Student;
@Component
public class JsonUtil {
	public School getSchoolDetails() {
		
		School school = new School();
		school.setName("My School");
		
		List<Student> students = new ArrayList<>();
		Student student1 = new Student();
		student1.setFirstName("Arun");
		student1.setLastName("SB");
		Grade grade1 = new Grade();
		grade1.setName("XI");
		student1.setGrade(grade1);
		
		Student student2 = new Student();
		student2.setFirstName("John");
		student2.setLastName("Taylor");
		Grade grade2 = new Grade();
		grade2.setName("X");
		student2.setGrade(grade2);
		
		Student student3 = new Student();
		student3.setFirstName("Malcom");
		student3.setLastName("Jr");
		Grade grade3 = new Grade();
		grade3.setName("VII");
		student3.setGrade(grade3);
		
		students.add(student1);
		students.add(student2);
		students.add(student3);
		
		school.setStudents(students);
		
		return school;
	}
}

Create a service class with the name SchoolService.java as shown below.

SchoolService.java

package com.asb.example.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@Service
public class SchoolService {
	@Autowired
	private JsonUtil jsonUtil;
	private static final ObjectMapper om = new ObjectMapper();
	public String getDetails() throws JsonProcessingException {
		return om.writeValueAsString(jsonUtil.getSchoolDetails());
	}
}

Create a controller layer

The actual operation of JsonPath will be implemented here.

We will also create different endpoints to get different JSON details by using JsonPath functions and queries.

SchoolController.java

package com.asb.example.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.asb.example.dto.Student;
import com.asb.example.service.SchoolService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
@RestController
public class SchoolController {
	@Autowired
	private SchoolService schoolService;
	private static final ObjectMapper om = new ObjectMapper();
	@GetMapping("/get-school-details")
	public ResponseEntity<String> getSchoolDetails() throws JsonProcessingException {
		return new ResponseEntity<>(schoolService.getDetails(), HttpStatus.OK);
	}
	@GetMapping("/get-students")
	public ResponseEntity<String> getStudentDetails() throws JsonProcessingException {
		String json = schoolService.getDetails();
		Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);
		List<Student> students = JsonPath.read(document, "$.students");
		return new ResponseEntity<>(om.writeValueAsString(students), HttpStatus.OK);
	}
	@GetMapping("/get-student-names")
	public ResponseEntity<String> getStudentNames() throws JsonProcessingException {
		String json = schoolService.getDetails();
		Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);
		List<String> students = JsonPath.read(document, "$.students[*].firstName");
		return new ResponseEntity<>(om.writeValueAsString(students), HttpStatus.OK);
	}
	@GetMapping("/student-count")
	public ResponseEntity<Integer> getStudentCount() throws JsonProcessingException {
		String json = schoolService.getDetails();
		Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);
		Integer count = JsonPath.read(document, "$.students.length()");
		return new ResponseEntity<>(count, HttpStatus.OK);
	}
	@GetMapping("/student/{firstName}")
	public ResponseEntity<List<Student>> getStudentCount(@PathVariable(value="firstName") String firstName) throws JsonProcessingException {
		String json = schoolService.getDetails();
		Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);
		List<Student> students = JsonPath.read(document, "$..[?(@.firstName=='" + firstName + "')]");
		return new ResponseEntity<>(students, HttpStatus.OK);
	}
}

The above controller has the following endpoints where different JsonPath features have been used.

  • /get-school-details: Returns complete JSON details.
  • /get-students: Returns list of available student JSON details.
  • /get-student-names: Returns array of student First name details.
  • /student-count: Returns count of students.
  • /student/{firstName}: Returns list of student, matched firstName field of Student JSON representation.

Also, there are many other features available in JsonPath and are explained in the documentation.

Run the application

Finally, start the spring boot example application and now we can test the endpoints one by one as shown below.

/get-school-details

jsonpath example

/get-students

jsonpath example spring

/get-student-names

jsonpath example spring

/student-count

jsonpath example spring

/student/{firstName}

jsonpath example spring

Conclusion

In conclusion, we learned how to use the JayWay JsonPath Maven library in spring development by creating an example application.

This open-source library is very helpful while writing the JUnit test cases, where we can evaluate response JSON objects retrieved from REST endpoints.

The sample code is available on GitHub. Happy coding! 🙂