summary
introduce
JsonPath is used to extract the content in json documents. It is a path expression just as xpath is used to extract the content in html or xml.
The json path package in the Java language is mentioned here. Other languages such as JavaScript can also use JsonPath, but the third package related to parsing is different. The package used below is supported by the Java language, but the syntax of json path expression is general.
If you use Gson to parse json and extract individual values, the code will be a lot of trouble, while JsonPath only needs a simple path expression to extract values, and the code is concise.
Generally, crawlers need to extract the content in json.
Its official website address: JsonPath
install
Its maven coordinates are as follows:
<dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>2.6.0</version> </dependency>
If an error is reported, caused by: Java Lang.noclassdeffounderror: Net / minidev / JSON / writer / jsonreaderi needs to add the following dependencies:
<dependency> <groupId>net.minidev</groupId> <artifactId>asm</artifactId> <version>1.0.2</version> <scope>test</scope> </dependency> <dependency> <groupId>net.minidev</groupId> <artifactId>json-smart</artifactId> <version>2.2.1</version> <scope>test</scope> </dependency>
introduction
The root member object in JsonPath is $. There are two ways for JsonPath to obtain data:
- Point representation: $ store.book[0].title
- Bracket notation: $['store']['book'][0]['title ']
Examples of getting started are as follows:
public class Test { @Test public void hello() { String json = "{\"msg\":\"hello world\"}"; String msg = JsonPath.read(json, "$.msg"); System.out.println(msg); } }
grammar
The json string used for the test is as follows:
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } }, "expensive": 10 }
Operator
The operators supported by JsonPath are as follows:
operation | explain |
---|---|
$ | Query the root element. This starts all path expressions. |
@ | The current node is processed by the filter predicate. |
* | Wildcard, use names or numbers anywhere if necessary. |
.. | Deep scan. Names can be used anywhere necessary. |
.<name> | Points, representing child nodes |
['<name>' (, '<name>')] | Parentheses indicate children |
[<number> (, <number>)] | Array index or index, index starts from 0 |
[start:end] | Array slicing operation |
[?(<expression>)] | Filter expressions. The expression must evaluate to a Boolean value. |
Examples are as follows:
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // Get all author values under store and book in json List<String> authors = JsonPath.read(json, "$.store.book[*].author"); System.out.println(authors);// ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"] } @Test public void test02() { // Get the values of all author s in all json List<String> authors = JsonPath.read(json, "$..author"); System.out.println(authors);// ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"] } @Test public void test03() { // Get all the books and bicycles Object obj = JsonPath.read(json, "$.store.*"); System.out.println(obj);// [[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],{"color":"red","price":19.95}] } @Test public void test04() { // Get the values of all price s under store in json List<Float> prices = JsonPath.read(json, "$.store..price"); System.out.println(prices);// [8.95,12.99,8.99,22.99,19.95] } @Test public void test05() { // Get the third book of the book array in json. Note that the index starts from 0, but also note that it returns an array rather than a Map collection List<Map<String, Object>> book = JsonPath.read(json, "$..book[2]"); System.out.println(book);// [{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}] } @Test public void test06() { // Get the penultimate book, that is, support reverse indexing, starting from - 1 List<Map<String, Object>> book = JsonPath.read(json, "$..book[-2]"); System.out.println(book);// [{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}] } @Test public void test07() { // Get the first two books, that is, the two books with indexes 0 and 1 in the array List<Map<String, Object>> books = JsonPath.read(json, "$..book[0,1]"); System.out.println(books);// [{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}] } @Test public void test08() { // Get all books from index 0 (included) to index 2 (excluded), i.e. [0,2]) List<Map<String, Object>> books = JsonPath.read(json, "$..book[:2]"); System.out.println(books);// [{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}] } @Test public void test09() { // Get all books from index 1 (included) to index 2 (excluded), i.e. [1,2]) List<Map<String, Object>> books = JsonPath.read(json, "$..book[1:2]"); System.out.println(books);// [{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99}] } @Test public void test10() { // Gets the last two values of the book array in json List<Map<String, Object>> books = JsonPath.read(json, "$..book[-2:]"); System.out.println(books);// [{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}] } @Test public void test11() { // Get the interval value from the third to the last of the book array in json, including the last one List<Map<String, Object>> books = JsonPath.read(json, "$..book[2:]"); System.out.println(books);// [{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}] } @Test public void test12() { // Gets all the values of isbn contained in the book array in json List<Map<String, Object>> books = JsonPath.read(json, "$..book[?(@.isbn)]"); System.out.println(books);// [{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}] } @Test public void test13() { // Get all the values of price < 10 in the book array in json List<Map<String, Object>> books = JsonPath.read(json, "$..book[?(@.price < 10)]"); System.out.println(books);// [{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}] } }
function
JsonPath also supports some functions that can be called at the end of the path. The output of the function is the output of the path expression. The output of the function is determined by the function itself. The following table:
function | describe | output |
---|---|---|
min() | Provides the minimum value of a numeric array | Double |
max() | Provides the maximum value of a numeric array | Double |
avg() | Provides the average value of an array of numbers | Double |
stddev() | Provides the standard deviation value of a numeric array | Double |
length() | Provide the length of the array | Integer |
sum() | Provides the sum of all native in the array | Double |
keys() | Provide all key names | Set |
concat(X) | Provides a concatinated version of the path output with a new item | like input |
append(X) | Adds an entry to the output array of the path expression | like input |
Examples are as follows:
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // How many books are there int length = JsonPath.read(json, "$..book.length()"); System.out.println(length); } @Test public void test02() { // Get the minimum book price double min = JsonPath.read(json, "$..book..price.min()"); System.out.println(min);// 8.95 } @Test public void test03() { // Get the maximum book price double max = JsonPath.read(json, "$..book..price.max()"); System.out.println(max);// 22.99 } @Test public void test04() { // Get average book price double avg = JsonPath.read(json, "$..book..price.avg()"); System.out.println(avg);// 13.48 } @Test public void test05() { // It is a statistical concept to obtain the standard deviation of the book price Object obj = JsonPath.read(json, "$..book..price.stddev()"); System.out.println(obj); } @Test public void test06() { // Get the total price of all books double sum = JsonPath.read(json, "$..book..price.sum()"); System.out.println(sum);// 53.92 } @Test public void test07() { // Get all the attribute key names of the second book Set<String> set = JsonPath.read(json, "$.store.book[2].keys()"); System.out.println(set);// [category, author, title, isbn, price] } }
Filter operator
A filter is a logical expression used to filter an array. A typical filter would be [? (@. Age > 18)], where @ represents the current item being processed. You can use the logical operators & & and | (representing and or, respectively) to create more complex filters. String literals must be enclosed in single or double quotation marks ([? (@. Color = ='Blue ')] or [? (@. color == "blue")])
Operator | describe |
---|---|
== | left equals right (note that 1 is not equal to '1') |
!= | Not equal to |
< | less than |
<= | Less than or equal to |
> | greater than |
>= | Greater than or equal to |
=~ | Match regular expressions, such as [? (@. name =~ /foo.*?/i)] |
in | The left exists on the right, such as [? (@. Size in ['s','m ']]] |
nin | The left does not exist on the right |
subsetof | On the left is a subset on the right, such as [? (@. sizes subsetof ['S','M','L ']]] |
anyof | The set on the left intersects the set on the right, such as [? (@. sizes anyof ['M','L']]] |
noneof | The left and right sets do not intersect with the right set, such as [? (@. sizes noneof ['M','L']]] |
size | The length of the left (array or string) should match the value on the right |
empty | The left (array or string) is empty |
Examples are as follows:
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // Find books with category equal to "fiction" List<Map<String, Object>> books = JsonPath.read(json, "$.store.book[?(@.category=='fiction')]"); System.out.println(books);// [{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}] } @Test public void test02() { // Find books whose category is not equal to "fiction" List<Map<String, Object>> books = JsonPath.read(json, "$.store.book[?(@.category!='fiction')]"); System.out.println(books);// [{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}] } @Test public void test03() { // Find books with price less than 10 List<Map<String, Object>> books = JsonPath.read(json, "$.store.book[?(@.price<10)]"); System.out.println(books);// [{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}] } @Test public void test04() { // Find books with a price greater than 10 List<Map<String, Object>> books = JsonPath.read(json, "$.store.book[?(@.price>10)]"); System.out.println(books);// [{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}] } @Test public void test05() { // Use regular expressions to match books with "of the" in title List<Map<String, Object>> books = JsonPath.read(json, "$.store.book[?(@.title =~ /.*of the.*/i)]"); System.out.println(books);// [{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}] } @Test public void test06() { // Query the books whose category exists in ["reference","abc"] List<Map<String, Object>> books = JsonPath.read(json, "$.store.book[?(@.category in ['reference','abc'])]"); System.out.println(books);// [{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}] } @Test public void test07() { // Query category does not exist in books of ["reference","abc"] List<Map<String, Object>> books = JsonPath.read(json, "$.store.book[?(@.category nin ['reference','abc'])]"); System.out.println(books);// [{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}] } @Test public void test08() { // ['S','M '] is a subset of ['S','M','L '], so it is matched String json = "{\"sizes\":[\"S\",\"M\"]}"; Object result = JsonPath.read(json, "$[?(@.sizes subsetof ['S','M','L'])]"); System.out.println(result);// [{"sizes":["S","M"]}] } @Test public void test09() { // ['S','M '] intersects with ['M','L '], where'M' is the intersecting value String json = "{\"sizes\":[\"S\",\"M\"]}"; Object result = JsonPath.read(json, "$[?(@.sizes anyof ['M','L'])]"); System.out.println(result);// [{"sizes":["S","M"]}] } @Test public void test10() { // ['S','X '] does not intersect with ['M','L '], so it is matched String json = "{\"sizes\":[\"S\",\"X\"]}"; Object result = JsonPath.read(json, "$[?(@.sizes noneof ['M','L'])]"); System.out.println(result); } @Test public void test11() { // Matching books with a title of only 9 characters List<Map<String, Object>> books = JsonPath.read(json, "$.store.book[?(@.title size 9)]"); System.out.println(books);// [{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}] } }
extend
The above syntax is enough for our daily use. Here are some extensions of JsonPath.
Reading documents
We all use jsonpath The read () method reads the content. If you only read it once, it is feasible. If you want to read it multiple times, it is not a good method, because this method needs to parse the entire json document every time, which consumes performance.
Therefore, if we need to read multiple paths, we can choose to parse the whole document first, and then parse the path to read the content.
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // Read multiple paths by parsing multiple documents long start1 = System.currentTimeMillis();// You can see how long they take String author0 = JsonPath.read(json, "$.store.book[0].author"); String author1 = JsonPath.read(json, "$.store.book[1].author"); long end1 = System.currentTimeMillis(); System.out.println(author0 + ", " + author1 + ", " + (end1 - start1));// Nigel Rees, Evelyn Waugh, 1218 // Read multiple paths by parsing a document [recommended] long start2 = System.currentTimeMillis(); Object document = Configuration.defaultConfiguration().jsonProvider().parse(json); String author2 = JsonPath.read(document, "$.store.book[0].author"); String author3 = JsonPath.read(document, "$.store.book[1].author"); long end2 = System.currentTimeMillis(); System.out.println(author2 + ", " + author3 + ", " + (end2 - start2));// Nigel Rees, Evelyn Waugh, 1 } }
The core code is:
String json="..."; Object document = Configuration.defaultConfiguration().jsonProvider().parse(json); String author2 = JsonPath.read(document, "$.store.book[0].author");
You can also use the following API, which makes the chain configuration flexible:
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // Resolve the path by reading the context ReadContext context = JsonPath.parse(json); List<String> authors = context.read("$.store.book..author"); System.out.println(authors);// ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"] // Or chain call List list = JsonPath .using(Configuration.defaultConfiguration()) .parse(json) .read("$.store.book..author", List.class); System.out.println(list);// ["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"] } }
When to return
Return result type
When using JsonPath, you should know exactly what type the result of the path is. JsonPath will try to convert to the expected type, such as:
// Throw Java Lang.classcastexception exception List<String> list = JsonPath.parse(json).read("$.store.book[0].author")// In fact, the returned string is a string, so it is not appropriate to use List to receive, so type conversion cannot be enforced // normal String author = JsonPath.parse(json).read("$.store.book[0].author")
When evaluating a path, you need to understand the concept of when the path is determined. The path is indeterminate if it contains the following:
- ..: deep scan operation
- ? (< expression >): expression
- [< number >, < number > (, < number >)]: multiple array indexes
The total number of uncertain paths returns a List that can be received by the List.
Return result mapping
- Simple object mapping
By default, the MappingProvider SPI provides a simple object mapper. This allows you to specify the required return type, and the MappingProvider will attempt to perform the mapping. To convert a Long timestamp to a Date:
public class JsonPathTest { @Test public void test01() { String json = "{\"timestamp\":1641519588137}"; Date date = JsonPath.parse(json).read("$.timestamp", Date.class); System.out.println(date);// Fri Jan 07 09:39:48 CST 2022 } }
- POJO object mapping
If it is a simple entity class mapping, such as Book, it can be as follows:
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { Book book = JsonPath.parse(json).read("$.store.book[0]", Book.class); System.out.println(book);// Book{category='reference', author='Nigel Rees', title='Sayings of the Century', isbin='null', price=8.95} } } class Book { private String category; private String author; private String title; private String isbn; private float price; public Book() { } public Book(String category, String author, String title, String isbn, float price) { this.category = category; this.author = author; this.title = title; this.isbn = isbn; this.price = price; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } @Override public String toString() { return "Book{" + "category='" + category + '\'' + ", author='" + author + '\'' + ", title='" + title + '\'' + ", isbin='" + isbn + '\'' + ", price=" + price + '}'; } }
However, in more complex cases, such as list < book >, you can consider configuring JsonPath to use JacksonMappingProvider or GsonMappingProvider, so that the output of JsonPath can be directly mapped to POJO s.
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // 1. Default configuration Configuration.setDefaults(new Configuration.Defaults() { // Note that GsonJsonProvider and GsonMappingProvider are created here, but the Gson package needs to be imported // You can also use jackson jsonprovider and jackson mapping provider, and you also need to import jackson package private final JsonProvider jsonProvider = new GsonJsonProvider(); private final MappingProvider mappingProvider = new GsonMappingProvider(); @Override public JsonProvider jsonProvider() { return jsonProvider; } @Override public Set<Option> options() { return EnumSet.noneOf(Option.class); } @Override public MappingProvider mappingProvider() { return mappingProvider; } }); // 2. Set generics. List < book > generics cannot be directly passed in the read() method, so you need to set generics in typeref < > TypeRef<List<Book>> typeRef = new TypeRef<List<Book>>() {}; // 3. Call the read() method to pass in the path expression and generic type and read the data List<Book> books = JsonPath.parse(json).read("$.store.book.*", typeRef); // 4. Print results for (Book book : books) { System.out.println(book); } // Book{category='reference', author='Nigel Rees', title='Sayings of the Century', isbin='null', price=8.95} // Book{category='fiction', author='Evelyn Waugh', title='Sword of Honour', isbin='null', price=12.99} // Book{category='fiction', author='Herman Melville', title='Moby Dick', isbin='0-553-21311-3', price=8.99} // Book{category='fiction', author='J. R. R. Tolkien', title='The Lord of the Rings', isbin='0-395-19395-8', price=22.99} } } class Book { private String category; private String author; private String title; private String isbn; private float price; public Book() { } public Book(String category, String author, String title, String isbn, float price) { this.category = category; this.author = author; this.title = title; this.isbn = isbn; this.price = price; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } @Override public String toString() { return "Book{" + "category='" + category + '\'' + ", author='" + author + '\'' + ", title='" + title + '\'' + ", isbin='" + isbn + '\'' + ", price=" + price + '}'; } }
predicate
There are three different ways to create filter predicates in JsonPath.
Inline predicate
Inline predicates are predicates defined directly in the path. For example:
List<Map<String, Object>> books = JsonPath.parse(json).read("$.store.book[?(@.price < 10)]");
Where [? (@. Price < 10)] is an inline predicate, which requires filtering books whose price is less than 10.
You can also use $$and |, that is, multiple filter conditions show the relationship between "and" and "or". For example, [? (@. Price < 10 & &@. Category = ='fiction ')] indicates books whose filter price is less than 10 and classified as fiction (multiple conditions are met at the same time) [? (@. Category = = 'reference' | @. Price > 10)] means filtering books classified as reference or with a price greater than 10 (as long as any condition is met).
One more! It means "not", for example [? (! (@. Price < 10 & &@. Category = ='fiction ')] means books whose price is neither less than 10 nor fiction.
Filter predicate
Predicates can be built using the Filter API, as follows:
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // Declare predicate filter Filter bookFilter = Filter.filter( // It is similar to the condition in SQL statement, that is, category = ='function '& & price < = 10 Criteria.where("category").is("fiction").and("price").lte(10) ); // Call the read method to pass in path expressions and predicate filters List<Map<String, Object>> books = JsonPath.parse(json).read("$.store.book[?]", bookFilter); System.out.println(books);// [{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99}] } }
be careful:
- Path expression $ store.book[?] Placeholder used in? To represent the filter in the path.
- When multiple filters are provided, they are applied in the order in which the number of placeholders matches the number of filters provided.
- You can operate [?,?] in one filter Multiple predicate placeholders are specified in, both of which must match.
- Filters can be used or(),. and(),. exists() to represent "or", "and" and "not".
Custom predicate
You can also implement your own predicates for more complex filtering.
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // Custom predicate Predicate booksPredicate = new Predicate() { @Override public boolean apply(PredicateContext context) { // The author's name is required to be exactly 10 characters return context.item(Map.class).get("author").toString().length() == 10; } }; // Call the read method to pass in path expressions and custom predicates List<Map<String, Object>> books = JsonPath.parse(json).read("$.store.book[?]", List.class, booksPredicate); System.out.println(books);// [{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95}] } }
Path vs value
By default, JsonPath is a return value, but it can also be required to return the full path of the matching element. As follows:
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // Configure and return the path Configuration conf = Configuration.builder().options(Option.AS_PATH_LIST).build(); // Incoming configuration read path List<String> pathList = JsonPath.using(conf).parse(json).read("$..author"); System.out.println(pathList);// ["$['store']['book'][0]['author']","$['store']['book'][1]['author']","$['store']['book'][2]['author']","$['store']['book'][3]['author']"] } }
Adjust configuration
When creating a configuration with options, there are several option flags that can change the default behavior.
DEFAULT_PATH_LEAF_TO_NULL
This option causes JsonPath to return null for the missing leaf, as shown in the following json:
[ { "name" : "john", "gender" : "male" }, { "name" : "ben" } ]
Get the gender in the second object. If the default configuration item is followed, an exception will be thrown. We hope it can return null when it does not exist, so we can set DEFAULT_PATH_LEAF_TO_NULL.
public class JsonPathTest { @Test public void test01() { String json = "[{\"name\":\"john\",\"gender\":\"male\"},{\"name\":\"ben\"}]"; Configuration conf = Configuration.defaultConfiguration(); // normal String gender0 = JsonPath.using(conf).parse(json).read("$[0]['gender']"); // Exception pathnotfoundexception throw String gender1 = JsonPath.using(conf).parse(json).read("$[1]['gender']");// com.jayway.jsonpath.PathNotFoundException: No results for path: $[1]['gender'] System.out.println(gender0 + ", " + gender1); } @Test public void test02() { String json = "[{\"name\":\"john\",\"gender\":\"male\"},{\"name\":\"ben\"}]"; Configuration conf2 = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL); // normal String gender0 = JsonPath.using(conf2).parse(json).read("$[0]['gender']"); // Normal (return null) String gender1 = JsonPath.using(conf2).parse(json).read("$[1]['gender']"); System.out.println(gender0 + ", " + gender1);// male, null } }
ALWAYS_RETURN_LIST
This option configures JsonPath to return a list, even if the path is determined.
For example, the result of $[0]['gender '] is a String. We can use String to receive it, but if we want to use list < String > to receive this single String, we need to configure ALWAYS_RETURN_LIST options.
public class JsonPathTest { @Test public void test01() { String json = "[{\"name\":\"john\",\"gender\":\"male\"},{\"name\":\"ben\"}]"; Configuration conf = Configuration.defaultConfiguration(); List<String> genders0 = JsonPath.using(conf).parse(json).read("$[0]['gender']");// java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List System.out.println(genders0); } @Test public void test02() { String json = "[{\"name\":\"john\",\"gender\":\"male\"},{\"name\":\"ben\"}]"; Configuration conf = Configuration.defaultConfiguration().addOptions(Option.ALWAYS_RETURN_LIST);// Set always return list List<String> genders0 = JsonPath.using(conf).parse(json).read("$[0]['gender']"); System.out.println(genders0);// ["male"] } }
SUPPRESS_EXCEPTIONS
This option ensures that exceptions are not propagated from the path evaluation. Follow these simple rules:
- If the option ALWAYS_RETURN_LIST exists, an empty list will be returned
- If the option ALWAYS_RETURN_LIST does not exist and returns null
JsonProvider SPI
JsonPath comes with five different jsonproviders:
- JsonSmartJsonProvider (default)
- JacksonJsonProvider
- JacksonJsonNodeJsonProvider
- GsonJsonProvider
- JsonOrgJsonProvider
- JakartaJsonProvider
The demonstrated configuration defaults can only be changed when the application is initialized. Strongly opposed to making changes at run time, especially in multithreaded applications.
Configuration.setDefaults(new Configuration.Defaults() { private final JsonProvider jsonProvider = new JacksonJsonProvider(); private final MappingProvider mappingProvider = new JacksonMappingProvider(); @Override public JsonProvider jsonProvider() { return jsonProvider; } @Override public MappingProvider mappingProvider() { return mappingProvider; } @Override public Set<Option> options() { return EnumSet.noneOf(Option.class); } });
Note: Jackson jsonprovider requires com fasterxml. jackson. Core: Jackson databind: 2.4.5, GsonJsonProvider needs to use COM. Com on your classpath google. code. Gson: gson: 2.3.1, that is, you need to import relevant jar packages to use.
Using JacksonJsonProvider or GsonJsonProvider, you can directly map the output of JsonPath to the entity class, as shown in the following example:
public class JsonPathTest { private String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void test01() { // 1. Default configuration Configuration.setDefaults(new Configuration.Defaults() { // Note that GsonJsonProvider and GsonMappingProvider are created here, but the Gson package needs to be imported // You can also use jackson jsonprovider and jackson mapping provider, and you also need to import jackson package private final JsonProvider jsonProvider = new GsonJsonProvider(); private final MappingProvider mappingProvider = new GsonMappingProvider(); @Override public JsonProvider jsonProvider() { return jsonProvider; } @Override public Set<Option> options() { return EnumSet.noneOf(Option.class); } @Override public MappingProvider mappingProvider() { return mappingProvider; } }); // 2. Set generics. List < book > generics cannot be directly passed in the read() method, so you need to set generics in typeref < > TypeRef<List<Book>> typeRef = new TypeRef<List<Book>>() {}; // 3. Call the read() method to pass in the path expression and generic type and read the data List<Book> books = JsonPath.parse(json).read("$.store.book.*", typeRef); // 4. Print results for (Book book : books) { System.out.println(book); } // Book{category='reference', author='Nigel Rees', title='Sayings of the Century', isbin='null', price=8.95} // Book{category='fiction', author='Evelyn Waugh', title='Sword of Honour', isbin='null', price=12.99} // Book{category='fiction', author='Herman Melville', title='Moby Dick', isbin='0-553-21311-3', price=8.99} // Book{category='fiction', author='J. R. R. Tolkien', title='The Lord of the Rings', isbin='0-395-19395-8', price=22.99} } } class Book { private String category; private String author; private String title; private String isbn; private float price; public Book() { } public Book(String category, String author, String title, String isbn, float price) { this.category = category; this.author = author; this.title = title; this.isbn = isbn; this.price = price; } public String getCategory() { return category; } public void setCategory(String category) { this.category = category; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } @Override public String toString() { return "Book{" + "category='" + category + '\'' + ", author='" + author + '\'' + ", title='" + title + '\'' + ", isbin='" + isbn + '\'' + ", price=" + price + '}'; } }
other
Encapsulation tool class
For using JsonPath to extract the contents of json strings and then encapsulate them into entity classes, you can do some simple encapsulation:
package json; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.Option; import java.lang.reflect.Field; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author lcl100 * @desc JsonPath Tool class * @date 2022-01-10 */ public class JsonPathUtil { /** * JsonPath to configure */ private final static Configuration configuration = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL); /** * Read the content in json according to the path expression * * @param json json string to be read * @param path JsonPath Path expression * @return Read results */ private static Object readPath(String json, String path) { Object result = null; try { result = JsonPath.using(configuration).parse(json).read(path); } catch (Exception ignored) { } return result; } /** * Extract the corresponding content in json according to the json template string, and then fill it into the corresponding mapping field in the class to extract the entity class * * @param json json string to be extracted * @param jsonPath json The template string stores the path relationship between the entity class attribute name and the corresponding content in json * @param clazz Entity class to be mapped * @param <T> Entity class generics * @return An entity class object that is extracted from the json string and assigned a value * @throws InstantiationException Exception creating instance object * @throws IllegalAccessException Field access permission exception */ public static <T> T getJsonObject(String json, String jsonPath, Class<T> clazz) throws InstantiationException, IllegalAccessException { // Extract all key value pairs in the json string jsonPath Map<String, Map<String, String>> arrayMap = new HashMap<>(); Map<String, String> objectMap = new HashMap<>(); // Determine whether the template string is a json object or a json array jsonPath = jsonPath.trim(); char firstChar = jsonPath.charAt(0); boolean isArray = false; if (firstChar == '[') { isArray = true; // Read all json objects in the json array. Each json object is a Map collection, and then put it into the List List<Map<String, String>> mapList = (List<Map<String, String>>) readPath(jsonPath, "$"); for (Map<String, String> map : mapList) { arrayMap.put(map.getOrDefault("NAME", null), map); } } else if (firstChar == '{') { isArray = false; // Read all key values into a Map set objectMap = (Map<String, String>) readPath(jsonPath, "$"); } // Get all fields of the class and assign values in turn T t = clazz.newInstance(); Class<?> tClass = t.getClass(); Field[] fields = tClass.getDeclaredFields(); for (Field field : fields) { // Extract the corresponding path expression according to the field name, and then extract the value in json according to the path expression String name = field.getName(); // Due to different template strings, the way of extracting paths is different String path = isArray ? (arrayMap.getOrDefault(name, null) != null ? arrayMap.get(name).get("PATH") : null) : objectMap.getOrDefault(name, null); // Read value according to path Object value = readPath(json, path); // If you are using a template string with a regular expression, additional processing is required if (isArray) { // Regular extraction Matcher matcher = Pattern.compile(arrayMap.getOrDefault(name, null).getOrDefault("REGEXP", null)).matcher(String.valueOf(value)); if (matcher.find()) { value = matcher.group(1); } } // Assign values to fields setField(field, t, value); } return t; } /** * Extract the corresponding content in json according to the json template string, and then fill it into the corresponding mapping field in the class to extract the entity class collection * * @param json json string to be extracted * @param jsonPath json The template string stores the path relationship between the entity class attribute name and the corresponding content in json * @param clazz Entity class to be mapped * @param <T> Entity class generics * @return Set of assigned entity classes * @throws InstantiationException Exception creating instance object * @throws IllegalAccessException Field access permission exception */ public static <T> List<T> getJsonList(String json, String jsonPath, Class<T> clazz) throws InstantiationException, IllegalAccessException { List<T> list = new ArrayList<>(); Map<String, Map<String, String>> arrayMap = new HashMap<>(); Map<String, String> objectMap = new HashMap<>(); // Determine the mode of template string according to whether there is "DATA" boolean isArray = jsonPath.contains("DATA"); if (isArray) {// This pattern uses regular expressions // It is directly an array containing multiple json objects, that is, multiple Map collections List<Map<String, String>> mapList = (List<Map<String, String>>) readPath(jsonPath, "$.DATA"); for (int i = 0; i < mapList.size(); i++) { Map<String, String> map = mapList.get(i); String name = map.get("NAME"); String path = map.get("PATH"); if (name != null && !"".equals(name.trim()) && path != null && !"".equals(path.trim())) { arrayMap.put(name, map); } } } else {// The pattern does not use regular expressions // It is directly a Map collection, including all key value pairs objectMap = (Map<String, String>) readPath(jsonPath, "$"); } // Calculate root_ The length of the array represented by the path represented by list in the json string String rootPath = (String) readPath(jsonPath, "$.ROOT_LIST"); int length = (int) readPath(json, rootPath + ".length()"); for (int j = 0; j < length; j++) { // Create entity class object T t = clazz.newInstance(); Class<?> tClass = t.getClass(); // Get all declared fields Field[] fields = tClass.getDeclaredFields(); for (Field field : fields) { // Field name String fieldName = field.getName(); // The value to be assigned to the field Object value; if (isArray) { // Filter out fields that do not need to be extracted if (arrayMap.getOrDefault(fieldName, null) == null) { continue; } // Reads the value of the specified path from json value = readPath(json, rootPath + "[" + j + "]" + arrayMap.getOrDefault(fieldName, null).get("PATH")); // Regular processing is required Matcher matcher = Pattern.compile(arrayMap.getOrDefault(fieldName, null).getOrDefault("REGEXP", null)).matcher(String.valueOf(value)); if (matcher.find()) { value = matcher.group(1); } } else { // Filter out fields that do not need to be extracted if (objectMap.getOrDefault(fieldName, null) == null) { continue; } // Reads the value of the specified path from json value = readPath(json, rootPath + "[" + j + "]" + objectMap.getOrDefault(fieldName, null)); } // Assign values to fields setField(field, t, value); } list.add(t); } return list; } /** * Assign values to the fields on the instance object according to the field type * * @param field Fields to be assigned * @param t Instance object * @param value Value to be assigned * @throws IllegalAccessException Field access permission exception */ private static void setField(Field field, Object t, Object value) throws IllegalAccessException { String typeName = field.getType().getTypeName(); field.setAccessible(true); if (typeName.endsWith("String")) { field.set(t, String.valueOf(value)); } else if (typeName.endsWith("byte")) { byte result = 0; try { result = Byte.parseByte(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("Byte")) { Byte result = null; try { result = Byte.valueOf(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("short")) { short result = 0; try { result = Short.parseShort(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("Short")) { Short result = null; try { result = Short.valueOf(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("int")) { int result = 0; try { result = Integer.parseInt(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("Integer")) { Integer result = null; try { result = Integer.valueOf(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("long")) { long result = 0L; try { result = Long.parseLong(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("Long")) { Long result = null; try { result = Long.valueOf(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("float")) { float result = 0F; try { result = Float.parseFloat(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("Float")) { Float result = null; try { result = Float.valueOf(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("double")) { double result = 0; try { result = Double.parseDouble(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("Double")) { Double result = null; try { result = Double.valueOf(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("boolean")) { boolean result = false; try { result = Boolean.parseBoolean(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("Boolean")) { Boolean result = null; try { result = Boolean.valueOf(value.toString()); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("char")) { char result = '\u0000'; try { result = value.toString().charAt(0); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("Character")) { Character result = null; try { result = value.toString().charAt(0); } catch (Exception ignored) { } field.set(t, result); } else if (typeName.endsWith("Date")) { Date result = null; // Only timestamp dates can be processed temporarily try { Matcher timestampMatcher = Pattern.compile("1[\\d]{9}").matcher(value.toString()); if (timestampMatcher.find()) { result = new Date(Long.parseLong(value.toString())); } } catch (Exception ignored) { } field.set(t, result); } else { System.out.println("Field type that cannot be converted: " + typeName); } } }
The test classes are as follows:
public class JsonPathUtilTest { private final String json = "{\"store\":{\"book\":[{\"category\":\"reference\",\"author\":\"Nigel Rees\",\"title\":\"Sayings of the Century\",\"price\":8.95},{\"category\":\"fiction\",\"author\":\"Evelyn Waugh\",\"title\":\"Sword of Honour\",\"price\":12.99},{\"category\":\"fiction\",\"author\":\"Herman Melville\",\"title\":\"Moby Dick\",\"isbn\":\"0-553-21311-3\",\"price\":8.99},{\"category\":\"fiction\",\"author\":\"J. R. R. Tolkien\",\"title\":\"The Lord of the Rings\",\"isbn\":\"0-395-19395-8\",\"price\":22.99}],\"bicycle\":{\"color\":\"red\",\"price\":19.95}},\"expensive\":10}"; @Test public void testGetJsonObject() throws InstantiationException, IllegalAccessException { // Note that in the jsonPath template expression, the key name is the attribute name in the entity class; The key value is the full path in the json string // Template string of the first form String jsonPath1 = "{\n" + " \"category\": \"$.store.book[0].category\",\n" + " \"author\": \"$.store.book[0].author\",\n" + " \"title\": \"$.store.book[0].title\",\n" + " \"isbn\": \"$.store.book[0].isbn\",\n" + " \"price\": \"$.store.book[0].price\"\n" + "}"; Book book1 = JsonPathUtil.getJsonObject(json, jsonPath1, Book.class); System.out.println(book1); // Template string of the second form String jsonPath2 = "[\n" + " {\n" + " \"NAME\": \"category\",\n" + " \"PATH\": \"$.store.book[0].category\",\n" + " \"REGEXP\": \"(.*)\"\n" + " },\n" + " {\n" + " \"NAME\": \"author\",\n" + " \"PATH\": \"$.store.book[0].author\",\n" + " \"REGEXP\": \"(.*)\"\n" + " },\n" + " {\n" + " \"NAME\": \"title\",\n" + " \"PATH\": \"$.store.book[0].title\",\n" + " \"REGEXP\": \"(.*)\"\n" + " },\n" + " {\n" + " \"NAME\": \"isbn\",\n" + " \"PATH\": \"$.store.book[0].isbn\",\n" + " \"REGEXP\": \"(.*)\"\n" + " },\n" + " {\n" + " \"NAME\": \"price\",\n" + " \"PATH\": \"$.store.book[0].price\",\n" + " \"REGEXP\": \"(\\\\d+\\\\.\\\\d+)\"\n" + " }\n" + "]"; Book book2 = JsonPathUtil.getJsonObject(json, jsonPath1, Book.class); System.out.println(book2); } @Test public void testGetJsonList() throws InstantiationException, IllegalAccessException { // Note, ROOT_LIST is a required field, indicating the root path of the list // Note that in the jsonPath template expression, the key name is the attribute name in the entity class; The key value is the relative path in the json string (relative to the root path of the list) // Template string of the first form String jsonPath1 = "{\n" + " \"ROOT_LIST\": \"$.store.book\",\n" + " \"category\": \".category\",\n" + " \"author\": \".author\",\n" + " \"title\": \".title\",\n" + " \"isbn\": \".isbn\",\n" + " \"price\": \".price\"\n" + "}"; List<Book> bookList1 = JsonPathUtil.getJsonList(json, jsonPath1, Book.class); for (Book book : bookList1) { System.out.println(book); } // Template string of the second form String jsonPath2 = "{\n" + " \"ROOT_LIST\": \"$.store.book\",\n" + " \"DATA\": [\n" + " {\n" + " \"NAME\": \"category\",\n" + " \"PATH\": \".category\",\n" + " \"REGEXP\": \"(.*)\"\n" + " },\n" + " {\n" + " \"NAME\": \"author\",\n" + " \"PATH\": \".author\",\n" + " \"REGEXP\": \"(.*)\"\n" + " },\n" + " {\n" + " \"NAME\": \"title\",\n" + " \"PATH\": \".title\",\n" + " \"REGEXP\": \"(.*)\"\n" + " },\n" + " {\n" + " \"NAME\": \"isbn\",\n" + " \"PATH\": \".isbn\",\n" + " \"REGEXP\": \"(.*)\"\n" + " },\n" + " {\n" + " \"NAME\": \"price\",\n" + " \"PATH\": \".price\",\n" + " \"REGEXP\": \"(\\\\d+\\\\.\\\\d+)\"\n" + " }\n" + " ]\n" + "}"; List<Book> bookList2 = JsonPathUtil.getJsonList(json, jsonPath2, Book.class); for (Book book : bookList2) { System.out.println(book); } } }
Please refer to: GitHub documentation.
Online JsonPath test
Website address: Online JSONPath test
It can help us quickly judge whether jsonpath is written correctly and whether the result is what we expect, without writing code to verify.