Snack3 之 Jsonpath使用

一、 Snack3 和 JSONPath 介绍

Snack3 是一个支持JSONPath的JSON框架。JSONPath是一个很强大的功能,也可以在Java框架中当作对象查询语言(OQL)来使用。

<dependency>
<groupId>org.noear</groupId>
<artifactId>snack3</artifactId>
<version>3.1.5.10</version>
</dependency>

Snack3 借签了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计。其下一切数据都以ONode表示,ONode也即 One node 之意,代表任何类型,也可以转换为任何类型。

  • 强调文档树的操控和构建能力
  • 做为中间媒体,方便不同格式互转
  • 高性能Json path查询(兼容性和性能很赞)
  • 支持序列化、反序列化

二、接口

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);
}
//...
}

默认使用缓存JSONPath解析对象,可提供几倍性能效果。

三、支持语法

  • 字符串使用单引号,例:['name']
  • 过滤操作用空隔号隔开,例:[?(@.type == 1)]
支持操作 说明
$ 表示根元素
@ 当前节点(做为过滤表达式的谓词使用)
* 通用配配符,可以表示一个名字或数字。
.. 深层扫描。 可以理解为递归搜索。
.<name> 表示一个子节点
['<name>' (, '<name>')] 表示一个或多个子节点
[<number> (, <number>)] 表示一个或多个数组下标(负号为倒数)
[start:end] 数组片段,区间为[start,end),不包含end(负号为倒数)
[?(<expression>)] 过滤表达式。 表达式结果必须是一个布尔值。
支持过滤操作符 说明
== left等于right(注意1不等于'1')
!= 不等于
< 小于
<= 小于等于
> 大于
>= 大于等于
=~ 匹配正则表达式[?(@.name =~ /foo.*?/i)]
in 左边存在于右边 [?(@.size in ['S', 'M'])]
nin 左边不存在于右边
支持尾部函数 说明
min() 计算数字数组的最小值
max() 计算数字数组的最大值
avg() 计算数字数组的平均值
sum() 计算数字数组的汇总值(新加的)

像这两种写法的语义是差不多:

$.store.book[0].title //建议使用这种
$['store']['book'][0]['title']

四、语法示例说明

JSONPath 说明
$ 根对象
$[-1] 最后元素
$[:-2] 第0个至倒数第2个
$[1:] 第1个之后所有元素(0为首个)
$[1,2,3] 集合中1,2,3个元素(0为首个)

五、接口使用示例

示例1:

读取对象的属性

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; }
}

示例2

读取集合多个元素的某个属性

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;

示例3

返回集合中多个元素

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;

示例4

按范围返回集合的子集

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;

示例5

通过条件过滤,返回集合的子集

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;

示例6

根据属性值过滤条件判断是否返回对象,修改对象,数组属性添加元素

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;

示例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));

具体用例测试请看下面:

String jsonStr = "{\n" +
" \"store\": {\n" +
" \"bicycle\": {\n" +
" \"color\": \"red\",\n" +
" \"price\": 19.95\n" +
" },\n" +
" \"book\": [\n" +
" {\n" +
" \"author\": \"刘慈欣\",\n" +
" \"price\": 8.95,\n" +
" \"category\": \"科幻\",\n" +
" \"title\": \"三体\"\n" +
" },\n" +
" {\n" +
" \"author\": \"itguang\",\n" +
" \"price\": 12.99,\n" +
" \"category\": \"编程语言\",\n" +
" \"title\": \"go语言实战\"\n" +
" }\n" +
" ]\n" +
" }\n" +
"}"; ONode o = ONode.load(jsonStr); //得到所有的书
ONode books = o.select("$.store.book");
System.out.println("books=::" + books); //得到所有的书名
ONode titles = o.select("$.store.book.title");
System.out.println("titles=::" + titles); //第一本书title
ONode title = o.select("$.store.book[0].title");
System.out.println("title=::" + title); //price大于10元的book
ONode list = o.select("$.store.book[?(price > 10)]");
System.out.println("price大于10元的book=::" + list); //price大于10元的title
ONode list2 = o.select("$.store.book[?(price > 10)].title");
System.out.println("price大于10元的title=::" + list2); //category(类别)为科幻的book
ONode list3 = o.select("$.store.book[?(category == '科幻')]");
System.out.println("category(类别)为科幻的book=::" + list3); //bicycle的所有属性值
ONode values = o.select("$.store.bicycle.*");
System.out.println("bicycle的所有属性值=::" + values); //bicycle的color和price属性值
ONode read = o.select("$.store.bicycle['color','price']");
System.out.println("bicycle的color和price属性值=::" + read);

打印结果

books=::[{"author":"刘慈欣","price":8.95,"category":"科幻","title":"三体"},{"author":"itguang","price":12.99,"category":"编程语言","title":"go语言实战"}]
titles=::["三体","go语言实战"]
title=::"三体"
price大于10元的book=::[{"author":"itguang","price":12.99,"category":"编程语言","title":"go语言实战"}]
price大于10元的title=::["go语言实战"]
category(类别)为科幻的book=::[{"author":"刘慈欣","price":8.95,"category":"科幻","title":"三体"}]
bicycle的所有属性值=::["red",19.95]
bicycle的color和price属性值=::["red",19.95]

Snack3 之 Jsonpath使用的更多相关文章

  1. Java 中 Snack3的使用

    网上看了一篇Java 中 Gson的使用,所以也跟着写篇Java 中 Snack3的使用 JSON 是一种文本形式的数据交换格式,从Ajax的时候开始流行,它比XML更轻量.比二进制容易阅读和编写:解 ...

  2. JSONPath入门之Snack3篇

    Snack3 for java 一个微型JSON框架 基于jdk8,60kb.有序列化反序列化.解析和转换.支持 Json path 查询. <dependency> <groupI ...

  3. JSONPath小试牛刀之Snack3

    最近在网上看了些JSONPath的入门例子.打算用Snack3这个框架写写例子.json path对`JSON的处理绝对是神器. 1.准备JSON字符串 { "store": { ...

  4. 精灵小巧的 Jsonpath 万精油:Snack3

    前几天和一个群里的朋友交流一个需求:在 Json 里像 XPath 一样找出节点,并修改值,然后输出新的Json. 很多人马上就会说,Jsonpath 啊. 是的 Jsonpath 确实能快速找出节点 ...

  5. Snack3 3.2 发布,轻量的Json+Jsonpath框架

    Snack3 是一个轻量的 JSON + Jsonpath 框架. 借鉴了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计.其下一切数据都以ONode表 ...

  6. 高性能 Jsonpath 框架,Snack3 3.2.29 发布

    Snack3,一个高性能的 JsonPath 框架 借鉴了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计.其下一切数据都以ONode表示,ONode也 ...

  7. 更强的 JsonPath 兼容性及性能测试之2022版(Snack3,Fastjson2,jayway.jsonpath)

    2022年了,重新做了一份json path的兼容性与性能测试.三个市面上流行框架比较性测试. 免责声明:可能测试得方式不对而造成不科学的结果(另外,机器不同结果会有不同),可以留言指出来.以下测试数 ...

  8. 更强的 JsonPath 兼容性及性能测试

    更强的 JsonPath 兼容性及性能测试 最近给自己的json框架snack3添加了json path支持.搞好之后,找了两个市面上流行框架比较性测试,以助自己改进框架的性能和兼容性. 测了一圈之后 ...

  9. Snack3 一个新的微型JSON框架

    Snack3 一个新的微型JSON框架 一个作品,一般表达作者的一个想法.因为大家想法不同,所有作品会有区别.就做技术而言,因为有很多有区别的框架,所以大家可以选择的框架很丰富. snack3.基于j ...

随机推荐

  1. Matlab交叉验证函数——crossvalind

    Generate cross-validation indices  生成交叉验证索引 Syntax语法 Indices = crossvalind('Kfold', N, K) %K折交叉验证   ...

  2. php实现微信拼手气红包

    $result = sendHB(3, 5); echo '<pre>'; var_export($result); echo array_sum($result); /** * 拼手气红 ...

  3. javascript基础修炼(13)——记一道有趣的JS脑洞练习题【华为云技术分享】

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/devcloud/article/detai ...

  4. 实战!轻松搭建图像分类 AI 服务

    人工智能技术(以下称 AI)是人类优秀的发现和创造之一,它代表着至少几十年的未来.在传统的编程中,工程师将自己的想法和业务变成代码,计算机会根据代码设定的逻辑运行.与之不同的是,AI 使计算机有了「属 ...

  5. Python装饰器总结,带你几步跨越此坑!

    欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...

  6. 链接脚本(Linker Script)应用实例(一)使用copy table将函数载入到RAM中运行

    将函数载入到RAM中运行需要以下三个步骤: (1)用编译器命令#pragma section "<section name>" <user functions&g ...

  7. ssm三大框架整合基本配置

    ssm三大框架整合基本配置 maven目录结构 数据库脚本mysql create database maven; use maven ; -- --------------------------- ...

  8. redis数据类型--set

    set是String的一个无序集合,最大存储量2^32-1(大概40多亿) 1.操作命令:(xxx可以是任意字符串) sadd xxx a b c d e (添加一个或多个) smembers xxx ...

  9. Java修炼——暂停线程的四个方法

    线程的获取方法:Thread.currentThread() 后面可以加上获取线程的名字 .getName() 这样就成功获取到了线程的名字.             Sleep会导致当前线程休眠一定 ...

  10. Es6中箭头函数与普通函数的区别

    Es6中箭头函数与普通函数的区别? 普通function的声明在变量提升中是最高的,箭头函数没有函数提升 箭头函数没有属于自己的this,arguments 箭头函数不能作为构造函数,不能被new,没 ...