A Java DSL for reading JSON documents using JsonPath expressions, similar to XPath for XML
—
Advanced filtering capabilities for creating complex queries with predicates, criteria builders, and custom filters. JsonPath supports sophisticated filtering using expressions within bracket notation.
Core Filter class providing factory methods and logical operations for combining filters.
/**
* Abstract base class for filtering JSON elements
*/
public abstract class Filter implements Predicate {
/**
* Creates a new Filter based on a single predicate
* @param predicate Predicate to wrap in filter
* @return Filter instance
*/
public static Filter filter(Predicate predicate);
/**
* Creates a new Filter based on multiple predicates (all must be true)
* @param predicates Collection of predicates that all must evaluate to true
* @return Filter instance combining all predicates with AND logic
*/
public static Filter filter(Collection<Predicate> predicates);
/**
* Parses a filter expression from string
* @param filter Filter string to parse (should match [?(<expression>)] format)
* @return Parsed Filter instance
* @throws InvalidCriteriaException If filter string is invalid
*/
public static Filter parse(String filter);
/**
* Applies this filter to the given context
* @param ctx Predicate context containing current item and root document
* @return true if filter matches, false otherwise
*/
public abstract boolean apply(PredicateContext ctx);
/**
* Combines this filter with another using OR logic
* @param other Predicate to combine with OR
* @return New Filter representing (this OR other)
*/
public Filter or(Predicate other);
/**
* Combines this filter with another using AND logic
* @param other Predicate to combine with AND
* @return New Filter representing (this AND other)
*/
public Filter and(Predicate other);
}Usage Examples:
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.Criteria;
import com.jayway.jsonpath.JsonPath;
import java.util.List;
String json = "{ \"books\": [" +
"{ \"category\": \"fiction\", \"author\": \"Smith\", \"price\": 8.95 }," +
"{ \"category\": \"fiction\", \"author\": \"Johnson\", \"price\": 12.99 }," +
"{ \"category\": \"reference\", \"author\": \"Brown\", \"price\": 15.50 }" +
"] }";
// Create filter using Criteria
Filter priceFilter = Filter.filter(Criteria.where("price").lt(10));
List<Object> cheapBooks = JsonPath.read(json, "$.books[?]", priceFilter);
// Parse filter from string
Filter categoryFilter = Filter.parse("[?(@.category == 'fiction')]");
List<Object> fictionBooks = JsonPath.read(json, "$.books[?]", categoryFilter);
// Combine filters with logical operations
Filter combinedFilter = priceFilter.and(categoryFilter);
List<Object> cheapFiction = JsonPath.read(json, "$.books[?]", combinedFilter);
// Using OR logic
Filter expensiveFilter = Filter.filter(Criteria.where("price").gt(15));
Filter extremePriceFilter = priceFilter.or(expensiveFilter);
List<Object> extremelyPricedBooks = JsonPath.read(json, "$.books[?]", extremePriceFilter);Core predicate interface and context for filter evaluation.
/**
* Interface for predicate functions used in filtering
*/
public interface Predicate {
/**
* Applies this predicate to the given context
* @param ctx Context containing current item and evaluation state
* @return true if predicate matches, false otherwise
*/
boolean apply(PredicateContext ctx);
/**
* Context interface providing access to current item and root document
*/
public interface PredicateContext {
/**
* Returns the current item being evaluated by this predicate
* @return Current document/item
*/
Object item();
/**
* Returns the current item mapped to the specified class
* @param clazz Target class for mapping
* @return Current item mapped to specified type
* @throws MappingException If mapping fails
*/
<T> T item(Class<T> clazz) throws MappingException;
/**
* Returns the root document (complete JSON being queried)
* @return Root document
*/
Object root();
/**
* Returns configuration used for evaluation
* @return Configuration instance
*/
Configuration configuration();
}
}Usage Examples:
import com.jayway.jsonpath.Predicate;
import com.jayway.jsonpath.JsonPath;
import java.util.Map;
// Custom predicate implementation
Predicate customPredicate = new Predicate() {
public boolean apply(PredicateContext ctx) {
Object item = ctx.item();
if (item instanceof Map) {
Map<String, Object> book = (Map<String, Object>) item;
String author = (String) book.get("author");
return author != null && author.length() > 5;
}
return false;
}
};
// Use custom predicate
List<Object> longAuthorNameBooks = JsonPath.read(json, "$.books[?]", customPredicate);
// Access different context elements
Predicate contextAwarePredicate = new Predicate() {
public boolean apply(PredicateContext ctx) {
// Current item being evaluated
Map<String, Object> currentBook = ctx.item(Map.class);
// Root document for comparison
Map<String, Object> root = (Map<String, Object>) ctx.root();
// Use configuration if needed
Configuration config = ctx.configuration();
return ((Number) currentBook.get("price")).doubleValue() > 10.0;
}
};Fluent API for building complex filter criteria with various comparison operations.
/**
* Builder class for creating filter predicates with fluent API
*/
public class Criteria implements Predicate {
/**
* Creates a new Criteria for the specified field
* @param key Field name to create criteria for
* @return Criteria instance for chaining operations
*/
public static Criteria where(String key);
/**
* Adds an AND condition for another field
* @param key Field name for additional criteria
* @return Criteria instance for chaining
*/
public Criteria and(String key);
/**
* Applies this criteria as a predicate
* @param ctx Predicate context
* @return true if criteria matches
*/
public boolean apply(PredicateContext ctx);
}Various comparison operators available in the Criteria builder.
/**
* Equality operations
*/
public Criteria is(Object o); // Alias for eq()
public Criteria eq(Object o); // Equal to
public Criteria ne(Object o); // Not equal to
/**
* Numeric comparison operations
*/
public Criteria lt(Object o); // Less than
public Criteria lte(Object o); // Less than or equal
public Criteria gt(Object o); // Greater than
public Criteria gte(Object o); // Greater than or equal
/**
* String operations
*/
public Criteria regex(Pattern pattern); // Regular expression match
/**
* Collection operations
*/
public Criteria in(Object... o); // Value in array
public Criteria in(Collection<?> c); // Value in collection
public Criteria nin(Object... o); // Value not in array
public Criteria nin(Collection<?> c); // Value not in collection
public Criteria contains(Object o); // Contains value
public Criteria all(Object... o); // Contains all values
public Criteria all(Collection<?> c); // Contains all values
public Criteria subsetof(Object... o); // Is subset of
public Criteria subsetof(Collection<?> c); // Is subset of collection
public Criteria anyof(Object... o); // Has any of values
public Criteria anyof(Collection<?> c); // Has any of collection values
public Criteria noneof(Object... o); // Has none of values
public Criteria noneof(Collection<?> c); // Has none of collection values
/**
* Type and size operations
*/
public Criteria type(Class<?> clazz); // Value is of specified type
public Criteria size(int size); // Array/string has specified size
public Criteria exists(boolean shouldExist); // Field exists/doesn't exist
public Criteria empty(boolean empty); // Array/string is empty/not empty
/**
* Advanced operations
*/
public Criteria matches(Predicate p); // Matches custom predicateUsage Examples:
import com.jayway.jsonpath.Criteria;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.JsonPath;
import java.util.Arrays;
import java.util.regex.Pattern;
String json = "{ \"books\": [" +
"{ \"category\": \"fiction\", \"author\": \"Herman Melville\", \"price\": 8.95, \"isbn\": \"123456789\", \"tags\": [\"classic\", \"literature\"] }," +
"{ \"category\": \"fiction\", \"author\": \"J.K. Rowling\", \"price\": 12.99, \"isbn\": \"987654321\", \"tags\": [\"fantasy\", \"young-adult\"] }," +
"{ \"category\": \"reference\", \"author\": \"Oxford Press\", \"price\": 15.50, \"tags\": [\"reference\", \"dictionary\"] }" +
"] }";
// Basic equality
Filter fictionFilter = Filter.filter(Criteria.where("category").eq("fiction"));
// Numeric comparisons
Filter cheapFilter = Filter.filter(Criteria.where("price").lt(10));
Filter expensiveFilter = Filter.filter(Criteria.where("price").gte(15));
// String operations with regex
Pattern authorPattern = Pattern.compile(".*Melville.*");
Filter authorFilter = Filter.filter(Criteria.where("author").regex(authorPattern));
// Collection operations
Filter isbnInList = Filter.filter(Criteria.where("isbn").in("123456789", "555666777"));
Filter hasFantasyTag = Filter.filter(Criteria.where("tags").contains("fantasy"));
Filter hasAllRequiredTags = Filter.filter(Criteria.where("tags").all("fiction", "literature"));
// Type and existence checks
Filter hasAuthor = Filter.filter(Criteria.where("author").exists(true));
Filter priceIsNumber = Filter.filter(Criteria.where("price").type(Number.class));
Filter shortIsbn = Filter.filter(Criteria.where("isbn").size(9));
// Complex criteria with AND conditions
Filter complexFilter = Filter.filter(
Criteria.where("category").eq("fiction")
.and("price").lt(15)
.and("tags").contains("classic")
);
// Using filters in queries
List<Object> fictionBooks = JsonPath.read(json, "$.books[?]", fictionFilter);
List<Object> cheapBooks = JsonPath.read(json, "$.books[?]", cheapFilter);
List<Object> complexResults = JsonPath.read(json, "$.books[?]", complexFilter);
// Empty/non-empty checks
String jsonWithEmptyArrays = "{ \"items\": [{ \"tags\": [] }, { \"tags\": [\"tag1\"] }] }";
Filter hasEmptyTags = Filter.filter(Criteria.where("tags").empty(true));
Filter hasNonEmptyTags = Filter.filter(Criteria.where("tags").empty(false));JsonPath also supports inline filter expressions directly in the path string.
Filter Expression Syntax:
// Basic comparisons
"$.books[?(@.price < 10)]" // Price less than 10
"$.books[?(@.category == 'fiction')]" // Category equals fiction
"$.books[?(@.author != 'Unknown')]" // Author not equal to Unknown
// Regular expressions
"$.books[?(@.author =~ /.*Smith.*/)]" // Author matches regex pattern
// Multiple conditions
"$.books[?(@.price < 10 && @.category == 'fiction')]" // AND condition
"$.books[?(@.price < 5 || @.price > 20)]" // OR condition
// Array operations
"$.books[?(@.tags[*] in ['fiction', 'drama'])]" // Any tag is in list
"$.books[?(@.tags.length() > 2)]" // More than 2 tags
// Existence checks
"$.books[?(@.isbn)]" // Has isbn field
"$.books[?(!@.discount)]" // Doesn't have discount field
// Root reference
"$.books[?(@.price < $.averagePrice)]" // Price less than root averagePriceUsage Examples:
import com.jayway.jsonpath.JsonPath;
import java.util.List;
// Direct inline filtering
List<Object> cheapBooks = JsonPath.read(json, "$.books[?(@.price < 10)]");
List<Object> fictionBooks = JsonPath.read(json, "$.books[?(@.category == 'fiction')]");
List<Object> authorBooks = JsonPath.read(json, "$.books[?(@.author =~ /.*Melville.*/)]");
// Complex inline expressions
List<Object> complexQuery = JsonPath.read(json,
"$.books[?(@.price < 15 && @.category == 'fiction' && @.tags[*] in ['classic'])]");
// Using functions in filters
List<Object> multipleTags = JsonPath.read(json, "$.books[?(@.tags.length() > 1)]");
// Existence checks
List<Object> hasIsbn = JsonPath.read(json, "$.books[?(@.isbn)]");
List<Object> noDiscount = JsonPath.read(json, "$.books[?(!@.discount)]");Install with Tessl CLI
npx tessl i tessl/maven-com-jayway-jsonpath--json-path