# JSONPath
相信作为测试
的大家,都熟悉JSONPath的用法,我这边就简短说明下。
简单的说,JSONPath就是JSON的查询语法
,我们都知道,在xml里面有XPATH给大家选择具体的路径,比如:
<student>
<name>woody</name>
</student>
2
3
我们可以用/student/name
获取到对应的学生名称,那JSONPath也是JSON数据的一种取值手段,它与XPATH比较相似。
尤其是我们不需要获取所有JSON数据的时候,比如我有一个学生数组,我只想取每个学生的名字,这种时候在我们无法
写代码去遍历数组并获取名字的时候,JSONPath就给我们带来了莫大的帮助。
# 背景
我们在做接口测试的时候,经常会需要对报文的一些数据进行替换,也要忽略一部分
字段,比如时间戳字段。
# JSONPath语法
JSONPath的语法比较简单,基本上看下面的表就可以了解一些常用的用法:
XPath | JsonPath | 说明 |
---|---|---|
/ | $ | 文档根元素 |
. | @ | 当前元素 |
/ | .或[] | 匹配下级元素 |
.. | N/A | 匹配上级元素,JsonPath不支持此操作符 |
// | .. | 递归匹配所有子元素 |
* | * | 通配符,匹配下级元素 |
@ | N/A | 匹配属性,JsonPath不支持此操作符 |
[] | [] | 下标运算符,根据索引获取元素,XPath索引从1开始,JsonPath索引从0开始 |
| | [,] | 连接操作符,将多个结果拼接成数组返回,可以使用索引或别名 |
N/A | [start :end :step] | 数据切片操作,XPath不支持 |
[] | ?() | 过滤表达式 |
N/A | () | 脚本表达式,使用底层脚本引擎,XPath不支持 |
() | N/A | 分组JsonPath不支持 |
上述数据来自Apifox
官网。
# Go中的JSONPath
我找了go里面star
最多的库: https://github.com/oliveagle/jsonpath (opens new window)
(不过并不是官方的实现,有轮子用我们就直接用吧)
下面我们来看一看一个具体的例子吧~
# 安装jsonpath库
go get github.com/oliveagle/jsonpath
# 解析图书馆的第二本书
假设我们有一个JSON数据,里面存放了很多本书,我现在要找到其中第二本的具体数据,其它我都不需要。
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
按照JSONPath文档给出的,我们应该这样写:
$.store.book[0]
我们就用这个库试试看!~
package main
import (
"encoding/json"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/oliveagle/jsonpath"
"log"
)
func main() {
var jsonData interface{}
data := `{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}`
json.Unmarshal([]byte(data), &jsonData)
lookup, err := jsonpath.JsonPathLookup(jsonData, "$.store.book[1]")
if err != nil {
log.Panic("解析jsonpath失败")
}
fmt.Println(lookup)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
我们来看看运行结果:
其实demo很简单,我们需要先把json(字符串)转为Go里面的对象,interface{}即可。接着通过JSONPath解析对应的Go对象(这个由此库实现),需要注意的是返回结果也是interface{},为了通用。
# 筛选出所有图书的名字
$.store.book[*].title
上述代码我们只需要把JSONPath替换为上述代码即可,我们来看看效果:
# 结语
JSONPath还有很多妙用,本文只是给大家介绍下关于Go使用JSONPath的方法,不过由于这个库还不是太完善,所以有一些高级用法还不支持,我们可以看看作者给出的表格: