Jsonpath use for Snack3

Posted by srboj on Tue, 10 Dec 2019 12:52:04 +0100

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]

Topics: Programming Attribute JSON Go less