Following the discussion of Json processing last time, the deeper Json structure is very inconvenient to access in Java code. If you do not define javabeans layer by layer, you need to hit a lot of keys when writing code, and the flexibility of access is not good.
An open source Java library called JSON-Path /JsonPath is designed to solve this problem. It is designed to emulate xpath to access JSON strings. It has powerful access logic and methods that can be used to quickly process JSON strings, especially when reading. When you look at the library, you can see that it is actually based on the JSONPath specification.
Jsonpath-xpath for JSON is not a formal specification. It is a specification for accessing JSON strings by Stefan Goessner. The main idea is to use XPath to provide a set of methods for JSON format. In terms of usage, this is a very practical specification. The basic access definitions for JSONPath and Xpath are compared as follows
XPath | JSONPath | Description |
---|---|---|
/ | $ | the root object/element |
. | @ | the current object/element |
/ | . or [] | child operator |
. | n/a | parent operator |
// | . | recursive descent. JSONPath borrows this syntax from E4X. |
* | * | wildcard. All objects/elements regardless their names. |
@ | n/a | attribute access. JSON structures don’t have attributes. |
[] | [] | subscript operator. XPath uses it to iterate over element collections and for predicates. In Javascript and JSON it is the native array operator. |
| | [and] | Union operator in XPath results in a combination of node sets. JSONPath allows alternate names or array indices as a set. |
n/a | [start:end:step] |
array slice operator borrowed from ES4. |
[] | ? (a) | applies a filter (script) expression. |
n/a | (a) | script expression, using the underlying script engine. |
(a) | n/a | grouping in Xpath |
Here’s an official example
{ "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}}}Copy the code
Here are some common uses
XPath | JSONPath | Result |
---|---|---|
/store/book/author |
$.store.book[*].author |
the authors of all books in the store |
//author |
$.. author |
all authors |
/store/* |
$.store.* |
all things in store, which are some books and a red bicycle. |
/store//price |
$.store.. price |
the price of everything in the store. |
//book[3] |
$.. book[2] |
the third book |
//book[last()] |
$.. book[(@.length-1)] $.. book[-1:] |
the last book in order. |
//book[position()<3] |
$.. The book [0, 1] $.. book[:2] |
the first two books |
//book[isbn] |
$.. book[?(@.isbn)] |
filter all books with isbn number |
//book[price<10] |
$.. book[?(@.price<10)] |
filter all books cheapier than 10 |
/ / * |
$.. * |
all Elements in XML document. All members of JSON structure. |
In addition to quick access, there is also a filtering feature that is quite useful, the second to last and the third to last in the table are good examples.
With the specification out of the way, let’s go back to the Java version of jSON-Path /JsonPath: Java JsonPath implementation, here praise Kallestenflo, his library design and implementation is very good, far beyond my expectations, than the official JS implementation is also much more complete, in Java method is very simple, first add dependency
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
</dependency>
Copy the code
The specific usage is as follows
String json = "...";
Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);
List<String> authors = JsonPath.read(document, "$.store.book[*].author");
String author0 = JsonPath.read(document, "$.store.book[0].author");
String author1 = JsonPath.read(document, "$.store.book[1].author");
// If you configure JsonPath to use JacksonMappingProvider or GsonMappingProvider you can even map your JsonPath output directly into POJO's.
Book book = JsonPath.parse(json).read("$.store.book[0]", Book.class);
// To obtain full generics type information, use TypeRef.
TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {};
List<String> titles = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[*].title", typeRef);
Copy the code
The FLUENT style API is as follows
String json = "...";
ReadContext ctx = JsonPath.parse(json);
List<String> authorsOfBooksWithISBN = ctx.read("$.store.book[?(@.isbn)].author");
List<Map<String, Object>> expensiveBooks = JsonPath
.using(configuration)
.parse(json)
.read("$.store.book[?(@.price > 10)]", List.class);
Copy the code
The Java version also provides some utility features:
- Supports Gson and Jackson
- There are built-in functions and dedicated filter operators
- JsonPath allows quick assignment
String newJson = JsonPath.parse(json).set("$['store']['book'][0]['author']", "Paul").jsonString();
- Query out of the JSON string, you can directly do JavaBean type conversion, here also support paradigm
Inline Predicates
Embedded predicates: Composite filtering conditions can be done directly in expressionsFilter Predicates
Custom conditional filtering predicates: You can customize proprietary filtering predicates that can be combined to implement very complex filtering conditions- Support the cache
Another useful part of this library is the data processed in crawler. In the process of crawler, each API on the server side corresponds to a set of Javabeans, and the necessity is not very strong. At this time, it is very suitable to play a role.
In addition, the most basic way to generate Json strings in Java is to use JavaBean serialization, but there are other ways to do this. Here is a quick way. If the format is more fixed, using a template language to generate Json strings can also be useful, the main advantage is that it is more intuitive. Another idea is to convert a Map object into a Json string, and there are a bunch of libraries that can do that.
In conclusion, there are a number of ways to make working with Json in Java fun and easy. These methods are borrowed from other languages or domains and converted into Java-specific tools that work well enough. The key is whether you have them in your toolbox.
Reference
- json-path/JsonPath: Java JsonPath implementation
- jsonpath online evaluator
- JSONPath – XPath for JSON
- JSON JSONPath – REST API Tutorial
- Introduction to JsonPath | Baeldung
- jsonpath – npm