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. Netty学习——基于netty实现简单的客户端聊天小程序

    Netty学习——基于netty实现简单的客户端聊天小程序 效果图,聊天程序展示 (TCP编程实现) 后端代码: package com.dawa.netty.chatexample; import ...

  2. 串的匹配算法--C语言实现

    串这种数据结构,使用是比较多的,但是它的一些方法在更高级的语言中,比如Java,Python中封装的比较完整了.在这里,我只写了串中使用最多的匹配算法,即串的定位操作.串的匹配算法常用的两种就是朴素匹 ...

  3. 【网络流相关】最大流的Dinic算法实现

    Luogu P3376 于\(EK\)算法求最大流时每一次只求一条增广路,时间复杂度会比较高.尽管实际应用中表现比较优秀,但是有一些题目还是无法通过. 那么我们就会使用\(Dinic\)算法实现多路增 ...

  4. 如何编写可怕的Java代码?

    我决定告诉你如何编写可怕的Java代码.如果你厌倦了所有这些美丽的设计模式和最佳实践,并且想写些疯狂的东西,请继续阅读. 如果你正在寻找有关如何编写良好代码的建议,请查看其它文章! 对一切使用异常 你 ...

  5. “洞察千里”,华为云HiLens如何让无人车智行天下

    作者:华为云 Rosie 随着人工智能的普及和渗透,"无人"的场景越来越丰富,无人超市.无人车.无人机等已经融入我们的生活. 乘着这股热浪,华为云携手上海交通大学学生创新中心举办了 ...

  6. 配置基于全局地址池的DHCP

    配置基于全局地址池的DHCP 配置基于全局地址池的DHCP服务器,从所有接口上的用户都可以选择该地址池中的地址,是个公共地址池. 实验 1.拓扑图 2.实验步骤 基本配置 开启DHCP功能 创建一个全 ...

  7. eclipse svn 问题记录

    1. 标记为合并,则是 舍弃的是资源库中的文件:覆盖,则是 舍弃本地文件

  8. Ganglia与Centreon整合构建智能化监控报警平台

    一.智能运维监控报警平台的组成 随着大数据时代的来临,运维工作的难度越来越大,每个运维人员都要面临不计其数的服务器和海量的数据,如何保证众多服务器和业务系统稳定高效地运行并尽量减少死机时间,成为考核运 ...

  9. CapSupport 的使用

    CapSupport 是在CAP的操作上做了一些封装 目的是让事务同时执行或者同时回滚 startup services.AddCapSupport((optaion) => { optaion ...

  10. WebAPI接口的自动化测试1

    自动化测试要满足四个条件: 1 - 自动化用例能够完成所有测试步骤   -------- postman不支持  没有完整的用例管理系统 2 - 每个用例的输入数据,必须要自动填入  -------- ...