JSONPath的语法和使用
最近一直再思考统一网易云音乐与qq音乐的api,做着做着写了好多代码
利用 linux的 tree -if 命令,展示一下这几天写的代码
root@angel:~# tree -if starter/
starter
starter/annotation
starter/annotation/BiAsyncAnnotaion.java
starter/annotation/MusicService.java
starter/configuration
starter/configuration/properties
starter/configuration/properties/YumbMusicServiceProperties.java
starter/configuration/properties/YumboMusicServiceNeteaseProperties.java
starter/configuration/properties/YumboMusicServiceQQProperties.java
starter/configuration/properties/YumboThreadPoolProperties.java
starter/configuration/YumboMusicAutoConfiguration.java
starter/configuration/YumboThreadPoolExecuterAutoConfiguration.java
starter/controller
starter/controller/MusicController.java
starter/controller/MVController.java
starter/controller/UserController.java
starter/entity
starter/entity/abstractMusic
starter/entity/abstractMusic/AbstractMusic.java
starter/entity/abstractMusic/AbstractYumboMusic.java
starter/entity/abstractMusic/AbstractYumboMV.java
starter/entity/netease
starter/entity/netease/NeteaseCloudMusicInfo.java
starter/entity/netease/NeteaseMusic.java
starter/entity/netease/NeteaseMV.java
starter/entity/otherMusic
starter/entity/otherMusic/OtherMusicInfo.java
starter/entity/qq
starter/entity/qq/QQMusicInfo.java
starter/entity/qq/QQMusic.java
starter/entity/qq/QQMV.java
starter/entity/Singer.java
starter/entity/yumboEnum
starter/entity/yumboEnum/MusicBitRateEnum.java
starter/entity/yumboEnum/MusicEnum.java
starter/entity/yumboEnum/MVBitRateEnum.java
starter/entity/yumboEnum/SearchTypeEnum.java
starter/entity/YumboMusic.java
starter/service
starter/service/YumboCommonService.java
starter/service/YumboMusicService.java
starter/service/YumboMVService.java
starter/SpringBootStarterMusicApplication.java
starter/utils
starter/utils/BiAsyncRequestUtils.java
starter/utils/JsonCombineUtils.java
starter/utils/YumboMusicRequestUtils.java12 directories, 34 files
root@angel:~# ls -lh starter
total 28K
drwxr-xr-x 2 root root 4.0K Jan 15 22:19 annotation
drwxr-xr-x 3 root root 4.0K Jan 15 22:19 configuration
drwxr-xr-x 2 root root 4.0K Jan 15 22:19 controller
drwxr-xr-x 7 root root 4.0K Jan 15 22:19 entity
drwxr-xr-x 2 root root 4.0K Jan 15 22:19 service
-rw-r--r-- 1 root root 361 Jan 15 22:19 SpringBootStarterMusicApplication.java
drwxr-xr-x 2 root root 4.0K Jan 15 22:19 utils
边写边思考问题,因为我想把两个音乐的api数据合成一个数据(会遇到 字段映射,多余字段,新增字段,字段之间的计数等问题)。在处理这些从网易云音乐api服务器和qq音乐服务器返回的json数据时,起初我是直接使用fastjson的get、put、parse、to这些方法来做转换和计算。
当我做了几个接口后,感觉这样一直在做重复且无聊的事情,我在思考更优的解决方法。比如模仿springboot
中yml
的使用,通过配置达到想要的功能,将json的转换规则进行解耦(不和代码直接绑定)。目的是做一个通用的工具,然后配置规则就能得到转换后的 json
经过自己的思考过后,打算尝试自己做一个工具,完成我想要的功能,于是就开始了设计规则
下面的json字符串是模板数据,也就是需要返回的数据字段的定义
- type表示字段的类型
- note则是说明
- weight表示权重
- count表示需要进行计算的表达式
- template则是模板数据(每一个字段对应数据的
json
结构)
{"total": {"type": "int","note": "所有歌曲的总数","weight": 1,"count": "qq.data.total + netease.result.songCount"},"qq": {"type": "int","note": "songs中来自qq音乐的条数","weight": 2,"count": "qq.songs[length]"},"netease": {"type": "int","note": "songs中来自网易云音乐的条数","weight": 2,"count": "netease.songs[length]"},"return_back": {"type": "int","note": "当前返回的总条数","weight": 3,"count": "this.qq + this.netease"},"template": {"name": "songs","type": "array"},"songs": [{"type": "qq","songName": "json.data.list[].songname","albumName": "json.data.list[].albumname","durationTime": "json.data.list[].interval","musicId": "json.data.list[].songmid","singer": [{"name": "json.data.list[].singer.name","id": "json.data.list[].singer.id"}],"mvId": "json.data.list[].vid","albumId": "json.data.list[].albummid"},{"type": "netease","songName": "json.result.songs[].name","albumName": "json.result.songs[].album.name","durationTime": "json.result.songs[].duration","musicId": "json.result.songs[].id","singer": [{"name": "json.result.songs[].artists[].name","id": "json.result.songs[].artists[].id"}],"mvId": "json.result.songs[].mvid","albumId": "json.result.songs[].album.id"}]
}
在处理并形成符合模板数据的过程中,我用到了fastjson中的JsonArray对象,在做遍历的时候,我在思考是java8的forEach方法遍历快还是通过get 索引更快,于是搜索了一下fastjson,于是找到了JsonPath
发现json-path
已经做了我想要做的事情,那么我就打算借用json-path
快速的将网易云音乐,qq音乐的api进行统一。只要定义好路径可以快速的提取自己需要的信息。
当然Fastjson
也提供了json-path
语法,搜索资料经过再三考虑决定使用Fastjson
以下内容来自github的文档,可以直接点击下面的文档地址
JSONPath文档地址(fastjson)
https://github.com/alibaba/fastjson/wiki/JSONPath
第一步、pom中引入fastjson
建议使用最新版的,我在引入的时候fastjson的版本是1.2.75
fastjson的maven仓库地址
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.75</version>
</dependency>
JsonPath语法
语法 | 作用 |
---|---|
$ |
根对象,例如$.name
|
[num] |
数组访问,其中num是数字,可以是负数。 例如 $[0].leader.departments[-1].name
|
[num0,num1,num2...]
|
数组多个元素访问,其中num是数字,可以是负数,返回数组中的多个元素。例如$[0,3,-2,5]
|
[start:end] |
数组范围访问,其中start和end是开始小表和结束下标,可以是负数,返回数组中的多个元素。例如$[0:5]
|
[start:end :step] |
数组范围访问,其中start 和end 是开始小表和结束下标,可以是负数;step 是步长,返回数组中的多个元素。例如$[0:5:2]
|
[?(key)] |
对象属性非空过滤,例如$.departs[?(name)]
|
[key > 123] |
数值类型对象属性比较过滤,例如$.departs[id >= 123] ,比较操作符支持=,!=,>,>=,<,<=
|
[key = ‘123’] |
字符串类型对象属性比较过滤,例如$.departs[name = '123'] ,比较操作符支持=,!=,>,>=,<,<=
|
[key like ‘aa%’] |
字符串类型like过滤,例如$.departs[name like 'sz*'] ,通配符只支持 % 支持 not like |
[key rlike ‘regexpr’] |
字符串类型正则匹配过滤,例如 departs[name like 'aa(.)*'] ,正则语法为jdk的正则语法,支持 not rlike
|
[key in (‘v0’, ‘v1’)] |
IN过滤, 支持字符串和数值类型。 例如: $.departs[name in ('wenshao','Yako')] $.departs[id not in (101,102)]
|
[key between 234 and 456] |
BETWEEN过滤, 支持数值类型,支持not between 例如: $.departs[ id between 101 and 201] $.departs[ id not between 101 and 201]
|
length() 或者 size() |
数组长度 例如 $.values.size() 支持类型 java.util.Map 和 java.util.Collection 和数组
|
keySet() |
获取Map的 keySet 或者对象的非空属性名称。例如$.val.keySet() 支持类型:Map 和 普通对象 不支持 :Collection和数组(返回null)
|
.
|
属性访问,例如$.name
|
..
|
deepScan属性访问,例如$..name
|
*
|
对象的所有属性,例如$.leader.*
|
['key']
|
属性访问。例如$['name']
|
['key0','key1']
|
多个属性访问。例如$['id','name']
|
下面两种写法的语义相同
$.store.book[0].title
和
$['store']['book'][0]['title']
语法示例
JSONPath | 语义 |
---|---|
$ | 根对象 |
$[-1] | 最后元素 |
$[:-2] | 第1个至倒数第2个 |
$[1:] | 第2个之后所有元素 |
$[1,2,3] | 集合中1,2,3个元素 |
第二步、根据语法以及实际中的json
数据编写jsonpath
jsonString是json字符串,jsonpath则是定义的path规则
String jsonpath="$.store.book[0:3]";// 定义规则
final Object read = JSONPath.read(jsonString, jsonpath);// 进行解析
final String s = JSONObject.toJSONString(read);// 将对象转换成字符串
public static class Entity {private Integer id;private String name;private Object value;public Entity() {}public Entity(Integer id, Object value) { this.id = id; this.value = value; }public Entity(Integer id, String name) { this.id = id; this.name = name; }public Entity(String name) { this.name = name; }public Integer getId() { return id; }public Object getValue() { return value; } public String getName() { return name; }public void setId(Integer id) { this.id = id; }public void setName(String name) { this.name = name; }public void setValue(Object value) { this.value = value; }
}
例1
读取集合多个元素的某个属性
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity("wenshao"));
entities.add(new Entity("ljw2083"));// 返回enties的所有名称
List<String> names = (List<String>)JSONPath.eval(entities, "$.name");
例2
返回集合中多个元素
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity("wenshao"));
entities.add(new Entity("ljw2083"));
entities.add(new Entity("Yako"));// 返回下标为1和2的元素
List<Entity> result = (List<Entity>)JSONPath.eval(entities, "[1,2]");
例3
按范围返回集合的子集
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity("wenshao"));
entities.add(new Entity("ljw2083"));
entities.add(new Entity("Yako"));// 返回下标从0到2的元素
List<Entity> result = (List<Entity>)JSONPath.eval(entities, "[0:2]");
例4
通过条件过滤,返回集合的子集
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));List<Object> result = (List<Object>) JSONPath.eval(entities, "[id in (1001)]");
例5
根据属性值过滤条件判断是否返回对象,修改对象,数组属性添加元素
Entity entity = new Entity(1001, "ljw2083");JSONPath.set(entity, "id", 123456); //将id字段修改为123456
JSONPath.set(entity, "value", new int[0]); //将value字段赋值为长度为0的数组
JSONPath.arrayAdd(entity, "value", 1, 2, 3); //将value字段的数组添加元素1,2,3
例6 keySet
使用keySet抽取对象的属性名,null值属性的名字并不包含在keySet结果中,使用时需要注意,详细可参考示例。
Entity e = new Entity();
e.setId(null);
e.setName("hello");
Map<String, Entity> map = Collections.singletonMap("e", e);
Collection<String> result;// id is null, excluded by keySet
result = (Collection<String>)JSONPath.eval(map, "$.e.keySet()");// result.seze()=1e.setId(1L);
result = (Collection<String>)JSONPath.eval(map, "$.e.keySet()");// result.seze()=2,因为id不为null,所以keySet()返回的就是id,name两个
JSONPath的语法和使用相关推荐
- python中path语句什么意思_python中jsonpath模块有何用法?
小编做项目的时候,遇到一个问题,虽然解决了,但是也是深入的思考的一番,遇到问题是这样的,我们返回的基本格式都是json,但是json都是层层递进的,如果想审核json中心找到字符串等内容,要一层一层的 ...
- python的jsonpath_python 提取json数据的jsonPath介绍及简单使用
为什么要用jsonpath 就跟为什么要用xpath一样,jsonpath的设计灵感来源于xpath.一个强大的json数据提取工具.让用户不用编写脚本就可以提取到相应的json数据. jsonpat ...
- python接口测试非json的断言_荐在接口自动化测试中,如何利用Pytest + JSONPath 进行接口响应断言...
之前有一篇文章,介绍了如何使用JSONSchema对接口响应进行断言,主要的适用场景是对响应的数据结构进行校验,保证客户端收到的数据结构稳定和合法.今天,介绍使用JSONPath对接口响应的值进行断言 ...
- python-json校验-jsonpath
本文为在霍格沃兹测试开发学社中学习到的一些技术,写出来分享给大家,希望有志同道合的小伙伴可以一起交流技术,一起进步~ 霍格沃兹启发 技术分享 | 接口自动化测试如何搞定 json 响应断言? 背景 在 ...
- python jsonpath模块
jsonpath jsonpath第三方模块.jsonpath是json的XPath工具,简单说就是从 字典对象 中查找数据更方便,可以解析多层嵌套的json数据. 不使用jsonpath时查询 字典 ...
- 在接口自动化测试中,如何利用Pytest + JSONPath 进行接口响应断言
之前有一篇文章,介绍了如何使用JSONSchema对接口响应进行断言,主要的适用场景是对响应的数据结构进行校验,保证客户端收到的数据结构稳定和合法.今天,介绍使用JSONPath对接口响应的值进行断言 ...
- JSON解析工具----JSONPath基本使用
转自:作者:琴水玉 https://www.cnblogs.com/lovesqcc/p/7821641.html JsonPath:从多层嵌套Json中解析所需要的值 问题 基本方案 JsonPat ...
- python编辑工具——jsonpath在线解析工具
每天进步一点点,关注我们哦,每天分享测试技术文章 本文章出自[码同学软件测试] 码同学公众号:自动化软件测试 码同学抖音号:小码哥聊软件测试 01 Jsonpath的定义 JsonPath是一种简单的 ...
- JsonPath用法详解
JSONPath是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本,包括Javascript.Python.PHP和Java. JSONPath的安装方法如下: pip i ...
最新文章
- pygame 移开的矩形留痕迹_Python之pygame学习矩形区域(5)
- 数据增删改查之三层架构(理解三层续)
- A - 数据结构实验之排序一:一趟快排
- 睡觉前后爆笑的情侣小两口~媳妇不要闹了~
- HDU 12O3 I NEED A OFFER!
- 用Python爬取漫画并转换格式为pdf和mobi
- Chrome浏览器启动参数大全(命令行参数)
- c语言printf输出格式
- 国内外各大搜索引擎登录入口
- 小程序提示 网络异常 Network Anomalies
- android蓝牙同步拨打电话状态,还不会用华为Watch打电话?这六个步骤要记清!
- 【原理分析】Google炫炸天的平衡自行车仅仅是概念吗?来看看惯性轮自行车吧...
- 常见的DNS攻击与相应的防御措施
- 高阶多项式合并同类项程序c语言,c语言实现两多项式相乘,并排序,合并同类项.doc...
- 中国学生常见的英文论文写作问题
- 0月租注册卡,2019助力公司发展新篇章
- 开放共赢 平安云AI生态合作开启
- 日复一日 - C++ (设计符合下述要求的日期类(Date))新人
- 庄思浩先生在清华大学的演讲(2002)
- node.js源码编译安装(linux)