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. Vue-Router中History模式【华为云分享】

    [摘要] vue-router的history模式的服务端支持 示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端> ...

  2. Spring MVC中的Controller是Serlvet吗?

    1. Controller不是Servlet DispatcherServler是Spring MVC中的唯一Servlet,(这点可通过查看FrameworkServlet的子类确认) Servle ...

  3. luogu P1712 [NOI2016]区间

    题目描述 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一 ...

  4. iOS App Extension入门

    转自简书:http://www.jianshu.com/p/8cf08db29356   iOS 10推出了很多新功能,其中有几个高调的变化:通知栏更加实用,电话可以防骚扰,iMessage变得更加有 ...

  5. 数据库Oracle的含义

    数据库的含义: 所谓的数据库其实就是数据的集合.用户可以对集合中的数据进行新增.查询.更新. 删除等操作.数据库是以一定方式储存在一起.能与多个用户共享.具有尽可能小的冗余度. 与应用程序彼此独立的数 ...

  6. 第七章 jQuery中的事件与动画

    事件的分类 基础事件: 鼠标事件 键盘事件 window事件 表单事件 复合事件: 鼠标光标悬停 鼠标连续点击 基础事件: 实例: mouseenter()和mouseover()用法的区别: mou ...

  7. 2017 ACM/ICPC 沈阳 L题 Tree

    Consider a un-rooted tree T which is not the biological significance of tree or plant, but a tree as ...

  8. 最简单易懂的linux系统基础优化

    第10章 linux的系统优化 10.1 系统的版本,内核查看 10.1.1 系统版本的查看 [root@oldboy6666 ~]# cat /etc/redhat-release CentOS L ...

  9. iSensor APP 之 摄像头调试 OV3640 OV2640 MT9d112 ov5642

    iSensor APP 之 摄像头调试  OV3640 OV2640 MT9d112 iSensor app 非常适合调试各种摄像头,已测试通过的sensor有: l  OV7670.OV7725.O ...

  10. eclipse新建maven项目报错Could not resolve arachetype org.apache.maven.archetypes:mmaven-archetype-quickstart:1.1 from any of the configured repositories

    使用eclipse新建maven项目,按下图所示选择后,报错 报错截图 报错详细信息 Could not resolve archetype org.apache.maven.archetypes:m ...