Snack3 之 Jsonpath使用
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使用的更多相关文章
- Java 中 Snack3的使用
网上看了一篇Java 中 Gson的使用,所以也跟着写篇Java 中 Snack3的使用 JSON 是一种文本形式的数据交换格式,从Ajax的时候开始流行,它比XML更轻量.比二进制容易阅读和编写:解 ...
- JSONPath入门之Snack3篇
Snack3 for java 一个微型JSON框架 基于jdk8,60kb.有序列化反序列化.解析和转换.支持 Json path 查询. <dependency> <groupI ...
- JSONPath小试牛刀之Snack3
最近在网上看了些JSONPath的入门例子.打算用Snack3这个框架写写例子.json path对`JSON的处理绝对是神器. 1.准备JSON字符串 { "store": { ...
- 精灵小巧的 Jsonpath 万精油:Snack3
前几天和一个群里的朋友交流一个需求:在 Json 里像 XPath 一样找出节点,并修改值,然后输出新的Json. 很多人马上就会说,Jsonpath 啊. 是的 Jsonpath 确实能快速找出节点 ...
- Snack3 3.2 发布,轻量的Json+Jsonpath框架
Snack3 是一个轻量的 JSON + Jsonpath 框架. 借鉴了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计.其下一切数据都以ONode表 ...
- 高性能 Jsonpath 框架,Snack3 3.2.29 发布
Snack3,一个高性能的 JsonPath 框架 借鉴了 Javascript 所有变量由 var 申明,及 Xml dom 一切都是 Node 的设计.其下一切数据都以ONode表示,ONode也 ...
- 更强的 JsonPath 兼容性及性能测试之2022版(Snack3,Fastjson2,jayway.jsonpath)
2022年了,重新做了一份json path的兼容性与性能测试.三个市面上流行框架比较性测试. 免责声明:可能测试得方式不对而造成不科学的结果(另外,机器不同结果会有不同),可以留言指出来.以下测试数 ...
- 更强的 JsonPath 兼容性及性能测试
更强的 JsonPath 兼容性及性能测试 最近给自己的json框架snack3添加了json path支持.搞好之后,找了两个市面上流行框架比较性测试,以助自己改进框架的性能和兼容性. 测了一圈之后 ...
- Snack3 一个新的微型JSON框架
Snack3 一个新的微型JSON框架 一个作品,一般表达作者的一个想法.因为大家想法不同,所有作品会有区别.就做技术而言,因为有很多有区别的框架,所以大家可以选择的框架很丰富. snack3.基于j ...
随机推荐
- 混淆矩阵-MATLAB代码详解
一.混淆矩阵 (一).简介 在人工智能中,混淆矩阵(confusion matrix)是可视化工具,特别用于监督学习,在无监督学习一般叫做匹配矩阵.在图像精度评价中,主要用于比较分类结果和实际测得值, ...
- 如何看一款app里面所包含的图片
在开发制作App的过程中,有时候会想看看一些精美的App里面所设计的素材.这个时候就需要用到我给大家展现的方法了.下面就看看该如何操作能让一个App呈现出它原始的一面,这次我以Any.Do为例给大家演 ...
- for循环使用element的折叠面板遇到的问题-3
需求:for循环渲染上去的表单怎么使用element的表单校验 之前做这个的时候,死活绑不上去,不知道哪里出了问题,后来解决办法是prop要注意用拼接,使它和索引的变量一致 <el-form-i ...
- 前端工具-定制ESLint 插件以及了解ESLint的运行原理
这篇文章目的是介绍如何创建一个ESLint插件和创建一个ESLint rule,用以帮助我们更深入的理解ESLint的运行原理,并且在有必要时可以根据需求创建出一个完美满足自己需求的Lint规则. 插 ...
- 与karma、angular的第一次亲密接触
首先要了解什么是karma,karma干嘛用的,它的好朋友jasmine又是啥?这些文章可以帮助你: karma干嘛的? angular与karma1 angular与karma2 看了以上几篇文章之 ...
- 大型情感剧集Selenium:1_介绍 #华为云·寻找黑马程序员#
学习selenium能做什么? 很多书籍.文章中是这么定义selenium的: Selenium 是开源的自动化测试工具,它主要是用于Web 应用程序的自动化测试,不只局限于此,同时支持所有基于web ...
- JavaEE基础(02):Servlet核心API用法详解
本文源码:GitHub·点这里 || GitEE·点这里 一.核心API简介 1.Servlet执行流程 Servlet是JavaWeb的三大组件之一(Servlet.Filter.Listener) ...
- 如何运用DDD - 领域服务
目录 如何运用DDD - 领域服务 概述 什么是领域服务 从实际场景下手 更贴近现实 领域服务VS应用服务 扩展上面的需求 最常见的认证授权是领域服务吗 使用领域服务 不要过多的使用领域服务 不要将过 ...
- Redis面试热点之底层实现篇
通过本文你将了解到以下内容: Redis的作者.发展演进和江湖地位 Redis面试问题的概况 Redis底层实现相关的问题包括:常用数据类型底层实现.SDS的原理和优势.字典的实现原理.跳表和有序集合 ...
- 创建自己的github仓库
作者: wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/20067595 一.创建自己的github仓库 CocoaPods都托 ...