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.java
12 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字符串是模板数据,也就是需要返回的数据字段的定义
1. type表⽰字段的类型
2. note则是说明
3. weight表⽰权重
4. count表⽰需要进⾏计算的表达式
5. template则是模板数据(每⼀个字段对应数据的json结构)
{
"total":{
"type":"int",
"note":"所有歌曲的总数",
"weight":1,
"count":"al + sult.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 + thisease"
},
"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":"sult.songs[].name",
"albumName":"sult.songs[].album.name", "durationTime":"sult.songs[].duration",
"musicId":"sult.songs[].id",
"singer":[
{
"name":"sult.songs[].artists[].name",
"id":"sult.songs[].artists[].id"
}
],
"mvId":"sult.songs[].mvid",
"albumId":"sult.songs[].album.id"
}
]
eval是做什么的}
  在处理并形成符合模板数据的过程中,我⽤到了fastjson中的JsonArray对象,在做遍历的时候,我在思考是java8的forEach⽅法遍历快还是通过get 索引更快,于是搜索了⼀下fastjson,于是到了JsonPath
  发现json-path已经做了我想要做的事情,那么我就打算借⽤json-path快速的将⽹易云⾳乐,qq⾳乐的api进⾏统⼀。只要定义好路径可以快速的提取⾃⼰需要的信息。
当然Fastjson也提供了json-path语法,搜索资料经过再三考虑决定使⽤Fastjson
以下内容来⾃github的⽂档,可以直接点击下⾯的⽂档地址
JSONPath⽂档地址(fastjson)
第⼀步、pom中引⼊fastjson
建议使⽤最新版的,我在引⼊的时候fastjson的版本是1.2.75
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
JsonPath语法
语法作⽤
$根对象,例如$.name
[num]数组访问,其中num是数字,可以是负数。例如$[0].leader.departments[-1].name
[num0,]数组多个元素访问,其中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 = ad(jsonString, jsonpath);// 进⾏解析
final String s = JSONString(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
读取集合多个元素的某个属性

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。