1. Introduction of Snack3 and JSONPath
Snack3 is a JSON framework that supports JSONPath.JSONPath is a powerful feature that can also be used as an Object Query Language (OQL) in the Java framework.
<dependency> <groupId>org.noear</groupId> <artifactId>snack3</artifactId> <version>3.1.5.10</version> </dependency>
Snack3 borrows Javascript variables declared by var, and Xml dom everything is Node's design.All of its next data is represented as ONode, which means One node, representing any type, and can be converted to any type.
- Emphasizing the manipulation and construction of the document tree
- As an intermediate medium to facilitate the conversion of different formats
- High performance Json path queries (good compatibility and performance)
- Support serialization, deserialization
2. Interfaces
public class ONode{ //... /** * Json path select * * @param jpath json path express * @param useStandard use standard mode(default: false) * @param cacheJpath cache json path parsing results */ public ONode select(String jpath, boolean useStandard, boolean cacheJpath) { return JsonPath.eval(this, jpath, useStandard, cacheJpath); } public ONode select(String jpath, boolean useStandard) { return select(jpath, useStandard, true); } public ONode select(String jpath) { return select(jpath, false); } //... }
Resolving objects using cached JSONPath by default provides several times the performance effect.
3. Supporting Grammar
- Use single quotation marks for strings, for example: ['name']
- Filtering operations are separated by a space separator, for example: [?(@.type == 1)]
Support Operations | Explain |
---|---|
$ | Represents the root element |
@ | Current node (used as a predicate of a filter expression) |
* | A universal matching character that can represent a name or number. |
.. | Deep scan.It can be understood as recursive search. |
.<name> | Represents a child node |
['<name>' (, '<name>')] | Represents one or more child nodes |
[<number> (, <number>)] | Represents one or more array subscripts (negative is reciprocal) |
[start:end] | Array fragment, interval [start, end], does not contain end (negative sign is reciprocal) |
[?(<expression>)] | Filter expressions.The result of the expression must be a Boolean value. |
Supports filter operators | Explain |
---|---|
== | 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 expression [?(@.name =~/foo. *?/i)] |
in | Left exists on right [?(@.size in ['S','M'])] |
nin | Left does not exist on right |
Support tail function | Explain |
---|---|
min() | Calculate the minimum value of a number array |
max() | Calculate the maximum of a number array |
avg() | Calculate the mean of a number array |
sum() | Calculates the summary value of an array of numbers (newly added) |
The semantics of writing like these are similar:
$.store.book[0].title //This is recommended
$['store']['book'][0]['title']
4. Explanation of grammar examples
JSONPath | Explain |
---|---|
$ | Root Object |
$[-1] | Last element |
$[:-2] | 0th to 2nd last |
$[1:] | All elements after the first (0 is the first) |
$[1,2,3] | 1,2,3 elements in the set (0 is first) |
5. Examples of interface use
Example 1:
Read the properties of an object
Entity entity = new Entity(123, new Object()); ONode n = ONode.load(entity); assert n.select("$.id").getInt() == 123; assert n.select("$.*").count() == 2; public static class Entity { public int id; public String name; public Object value; public Entity(int id, Object value) { this.id = id; this.value = value; } public Entity(String name) { this.name = name; } }
Example 2
Read an attribute of multiple elements in a collection
List<Entity> entities = new ArrayList<Entity>(); entities.add(new Entity("wenshao")); entities.add(new Entity("ljw2083")); ONode n = ONode.load(entities); List<String> names = n.select("$.name").toObject(List.class); assert names.size() == 2;
Example 3
Returns multiple elements in a collection
List<Entity> entities = new ArrayList<Entity>(); entities.add(new Entity("wenshao")); entities.add(new Entity("ljw2083")); entities.add(new Entity("Yako")); ONode n = ONode.load(entities); List<Entity> result = n.select("$[1,2]").toObject((new ArrayList<Entity>() {}).getClass()); assert result.size() == 2;
Example 4
Returns a subset of a set by range
List<Entity> entities = new ArrayList<Entity>(); entities.add(new Entity("wenshao")); entities.add(new Entity("ljw2083")); entities.add(new Entity("Yako")); ONode n = ONode.load(entities); List<Entity> result = n.select("$[0:2]").toObject((new ArrayList<Entity>(){}).getClass()); assert result.size() == 2;
Example 5
Returns a subset of a set by conditional filtering
List<Entity> entities = new ArrayList<Entity>(); entities.add(new Entity(1001, "ljw2083")); entities.add(new Entity(1002, "wenshao")); entities.add(new Entity(1003, "yakolee")); entities.add(new Entity(1004, null)); ONode n = ONode.load(entities); ONode rst = n.select("$[?($.id in [1001,1002])]"); assert rst.count() == 2;
Example 6
Judges whether to return an object, modifies the object, and adds elements to an array property based on a property value filter condition
Entity entity = new Entity(1001, "ljw2083"); ONode n = ONode.load(entity); assert n.select("$[?(id == 1001)]").isObject(); assert n.select("$[?(id == 1002)]").isNull(); n.select("$").set("id",123456); assert n.get("id").getInt() == 123456; n.get("value").add(1).add(2).add(3); assert n.get("value").count() == 3;
Example 7
Map root = Collections.singletonMap("company", Collections.singletonMap("departs", Arrays.asList( Collections.singletonMap("id", 1001), Collections.singletonMap("id", 1002), Collections.singletonMap("id", 1003) ) )); ONode n = ONode.load(root); List<Object> ids = n.select("$..id").toObject(List.class); assertEquals(3l, ids.size()); assertEquals(1001l, ids.get(0)); assertEquals(1002l, ids.get(1)); assertEquals(1003l, ids.get(2));
For a specific use case test, see the following:
String jsonStr = "{\n" + " \"store\": {\n" + " \"bicycle\": {\n" + " \"color\": \"red\",\n" + " \"price\": 19.95\n" + " },\n" + " \"book\": [\n" + " {\n" + " \"author\": \"Liu Cixin\",\n" + " \"price\": 8.95,\n" + " \"category\": \"science fiction\",\n" + " \"title\": \"Trisomy\"\n" + " },\n" + " {\n" + " \"author\": \"itguang\",\n" + " \"price\": 12.99,\n" + " \"category\": \"Programing language\",\n" + " \"title\": \"go Language Actual\"\n" + " }\n" + " ]\n" + " }\n" + "}"; ONode o = ONode.load(jsonStr); //Get all the books ONode books = o.select("$.store.book"); System.out.println("books=::" + books); //Get all the titles ONode titles = o.select("$.store.book.title"); System.out.println("titles=::" + titles); //First book title ONode title = o.select("$.store.book[0].title"); System.out.println("title=::" + title); //book with price greater than 10 yuan ONode list = o.select("$.store.book[?(price > 10)]"); System.out.println("price Greater than 10 yuan book=::" + list); //title with price greater than 10 yuan ONode list2 = o.select("$.store.book[?(price > 10)].title"); System.out.println("price Greater than 10 yuan title=::" + list2); //Category is a science fiction book ONode list3 = o.select("$.store.book[?(category == 'science fiction')]"); System.out.println("category(category)For science fiction book=::" + list3); //All property values of bicycle ONode values = o.select("$.store.bicycle.*"); System.out.println("bicycle All attribute values=::" + values); //bicycle color and price attribute values ONode read = o.select("$.store.bicycle['color','price']"); System.out.println("bicycle Of color and price Attribute Value=::" + read);
Print results
books=::[{"author":"Liu Cixin","price":8.95,"category":"science fiction","title":"Trisomy"},{"author":"itguang","price":12.99,"category":"Programing language","title":"go Language Actual"}] titles=::["Trisomy","go Language Actual"] title=::"Trisomy" price Greater than 10 yuan book=::[{"author":"itguang","price":12.99,"category":"Programing language","title":"go Language Actual"}] price Greater than 10 yuan title=::["go Language Actual"] category(category)For science fiction book=::[{"author":"Liu Cixin","price":8.95,"category":"science fiction","title":"Trisomy"}] bicycle All attribute values=::["red",19.95] bicycle Of color and price Attribute Value=::["red",19.95]