JSONPath is a powerful tool for querying JSON data, similar to XPath for XML. Combining JSONPath with Jackson, a popular Java library for JSON processing, allows for advanced mapping of JSON structures to Java objects. This tutorial demonstrates how to map JSONPath expressions using Jackson and Jayway JsonPath.
Prerequisites
When working with JSON in Java, it’s often necessary to extract specific data from complex structures. While Jackson provides robust mechanisms for mapping JSON fields to Java objects, there are scenarios where JSONPath, a query language for JSON, can complement Jackson’s functionality. This tutorial illustrates how to leverage JSONPath expressions for advanced data mapping in Java applications.
To run this tutorial examples, you will need the following tools:
- Java Development Kit (JDK) installed
- Jackson library (com.fasterxml.jackson.core)
- Jayway JsonPath library (com.jayway.jsonpath)
Then, add the following dependencies to your Maven project:
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.0</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
A practical JSON Example
Consider the following JSON structure:
{
"person": {
"name": "John Doe",
"phoneNumbers": [
{
"type": "home",
"number": "123-456-7890"
},
{
"type": "work",
"number": "098-765-4321"
}
]
}
}
In this article, we will show how to map the type attribute of the first phone number ($.phoneNumbers[:1].type) to a field in a Java class.
Step 1: Create the Java Class
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.jayway.jsonpath.JsonPath;
import com.fasterxml.jackson.databind.JsonNode;
public class Person {
private String name;
@JsonIgnore // Exclude this field from automatic mapping
private String firstPhoneType;
@JsonCreator
public Person(@JsonProperty("name") String name, @JsonProperty("phoneNumbers") JsonNode phoneNumbers) {
this.name = name;
// Use JSONPath to extract the type of the first phone number
String json = phoneNumbers.toString();
this.firstPhoneType = JsonPath.parse(json).read("$[0].type");
}
public String getName() {
return name;
}
public String getFirstPhoneType() {
return firstPhoneType;
}
public void setFirstPhoneType(String firstPhoneType) {
this.firstPhoneType = firstPhoneType;
}
}
Step 2: Write the Test Code
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonPathMappingExample {
public static void main(String[] args) throws Exception {
String json = """
{
"person": {
"name": "John Doe",
"phoneNumbers": [
{ "type": "home", "number": "123-456-7890" },
{ "type": "work", "number": "098-765-4321" }
]
}
}
""";
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(json).path("person");
// Map the JSON to the Person object
Person person = mapper.treeToValue(rootNode, Person.class);
System.out.println("Name: " + person.getName());
System.out.println("First Phone Type: " + person.getFirstPhoneType());
}
}
Step 3: Run the Code
Compile and run the program. The output should be:
Name: John Doe First Phone Type: home
JSON Annotations
Within this article, we have used the following annotations:
JsonCreator: Customizes object creation during deserialization.JsonProperty: Maps JSON fields to constructor parameters.JsonIgnore: Prevents automatic serialization/deserialization of specific fields.JsonPath: Reads and applies JSONPath queries on thephoneNumbersJSON node to extract the desired value.
Besides, if you need a reusable approach for mapping JSONPath expressions, you can create a custom annotation and a deserialization handler. This can be useful for projects requiring extensive JSONPath mappings.
Conclusion
By combining Jackson and Jayway JsonPath, you can map JSONPath expressions to Java object fields, enabling fine-grained control over JSON parsing and data extraction.