在平常的工作中,遇到的接口响应格式绝大多数都是JSON格式,对于这种格式的数据有时候又爱又恨。很多时候要看懂层级,很多人会使用一些格式化工具(包括在线工具)。我自己写了一个方法来处理JSON格式的数据,之前写过文章:将json数据格式化输出到控制台,后来又更新了一些其他功能,修复了一些BUG,展示格式如下:

INFO-> 当前用户:fv,IP:192.168.0.102,工作目录:/Users/fv/Documents/workspace/funtester/,系统编码格式:UTF-8,系统Mac OS X版本:10.16
INFO->
~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~
> {
> ① . "msg":"FunTester",
> ① . "new":{
> ② . . . "36safs3":324,
> ② . . . "36s234s3":324,
> ② . . . "32432":4324,
> ② . . . "data":{
> ③ . . . . . "32":411324
> ② . . . }
> ① . },
> ① . "new21":322
> }
~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~ JSON ~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~~☢~

Process finished with exit code 0

复制代码


在本文中,我们将学习如何使用​​jq​​命令行优雅地处理​​JSON​​格式数据。

​jq​​可在各种平台上运行,可用于​​Linux​​、​​Windows​​和​​Mac OS​​。

对于以下许多示例,我们将使用一个名为​​FunTester.json​​的文件,其中包含以下​​JSON​​内容:

{
"name": "FunTester",
"article": [{
"author": "tester1",
"title": "ApiTest"
}, {
"author": "tester2",
"title": "performanceTest"
}
]
}
复制代码

jq基本语法

通常,通过将​​JSON​​管道输送到其标准输入来调用​​jq​​。如下:

FunTester:~ fv$ echo '{"name":"FunTester"}' | jq
{
"name": "FunTester"
}
复制代码

没有任何参数,​​jq​​只是输出​​JSON​​输入数据,这里输出数据已重新格式化。​​jq​​默认情况下输出格式的​​JSON​​。我们可以将少量的​​JSON​​数据通过管道传递给​​jq​​并获得格式正确的输出。

​jq​​可以使用一个或多个过滤器作为参数。最简单的过滤器是​​.​​。返回整个​​JSON​​数据的内容,这一点跟​​JsonPath​​类似,有兴趣的同学可以翻一翻我写过的​​JsonPath​​的文章。

下面的​​shell​​跟上面的命令行结果是一致的。

​echo '{"name":"FunTester"}' | jq '.'​

现在,我们可以向过滤器添加一个简单的对象标识符。为此,我们将使用前面提到的​​FunTester.json​​文件。通过​​.name​​获取名字的内容。

FunTester:Downloads fv$ cat FunTester.json | jq '.name'
"FunTester"
复制代码

可以使用​​[]​​语法获取数组信息:

FunTester:Downloads fv$ cat FunTester.json | jq '.article[1]'
{
"author": "tester2",
"title": "performanceTest"
}
复制代码

同理,我们可以将这两个语法组合起来:

FunTester:Downloads fv$ cat FunTester.json | jq '.article[1].title'
"performanceTest"
复制代码

如何我们想提取数组对象中某一个​​key​​的​​value​​集合,可以这么写:

FunTester:Downloads fv$ cat FunTester.json | jq '.article[].title'
"ApiTest"
"performanceTest"
复制代码

处理响应

当然,我们也可以用​​jq​​处理响应结果。这是一个​​jq​​常见用法,我用​​moco API​​封装框架,将上面的​​JSON​​数据当做一个接口的响应。

此处省略代码500行
server.get(urlOnly("/jq/test")).response(RWUtil.readTextByString("/Users/fv/Downloads/FunTester.json"))
此处省略代码500行
复制代码

我们首先验证接口正常,​​URL​​为​http://localhost:12345/jq/test​​,放到浏览器中能够看到​​FunTester.json​​文件的内容,为了不干扰各位阅读,这里就不重复放了。

下面我们用​​curl​​命令访问接口,并获取响应结果,然后使用​​jq​​命令获取一些值的集合。

FunTester:Downloads fv$ curl http://localhost:12345/jq/test | jq '.name,.article[1].author'
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 223 100 223 0 0 13937 0 --:--:-- --:--:-- --:--:-- 13937
"FunTester"
"tester2"

复制代码

这个地方,我在此处使用逗号分隔了两个不同的过滤器。

相比​​JsonPath​​工具,​​jq​​更像是命令行版本的​​JsonPath​​,而且输出格式方面非常不错的效果。接下来,我会继续探索​​jq​​工具的函数语法使用。