之前的文章使用jq处理JSON数据(一)中,我分享了jq
工具的基本用法。今天开始分享jq
的高阶使用,包括管道符、函数以及格式转换。
管道符和函数
在这个章节中中,将分享jq
更多过滤JSON
数据的方法。
使用|
运算符,我们可以结合两个过滤器。它的工作原理与Unix
系统管道符类似。左边的过滤器的输出传递到右边的过滤器。
请注意:.name.first
与.name | .first
使用结果是完全相同的,就将JSON
数据中.name
节点数据传递到第二个过滤器,然后选择.first
。
管道可以跟其他功能组合。例如,我们可以使用keys
函数来获取JSON
数据某个节点的键集合:
✘ fv@FunTester � ~/Downloads � cat FunTester.json | jq '. | keys'
[
"article",
"name"
]
fv@FunTester � ~/Downloads �
使用length
函数,我们可以获得数组中元素的数量长度:
fv@FunTester � ~/Downloads � cat FunTester.json | jq '. | keys | length'
2
length
函数的输出取决于输入元素:
- 如果传递了字符串,则返回字符
length
- 对于数组,返回元素个数
length
或者size
- 对于对象,返回键-值对的
size
我们还可以将length
函数跟运算符组合使用:
fv@FunTester � ~/Downloads � cat FunTester.json | jq '. | keys | length > 1'
true
还有一个更厉害的筛选函数select
,有点MySQL
数据库的意味。
✘ fv@FunTester � ~/Downloads � cat FunTester.json | jq '.article[] | select (.author == "tester2")'
{
"author": "tester2",
"title": "performanceTest"
}
select
函数后面跟的boolean
表达式还可以是其他很多种形式,这里不再意义演示。
转换格式
这个章节,我将分享一些使用jq
将原来JSON
数据组合转换其他格式的技巧。
先来拼接一个简单的JSON
格式数据:
fv@FunTester � ~/Downloads � cat FunTester.json | jq '{(.article[0].title): "FunTester"}'
{
"ApiTest": "FunTester"
}
这个例子中,首先我创建了一个只有一对键值对的JSON
对象,其中key
是从原来数据中取到的,表达式为(.article[0].title)
,这个在上一篇文章中已经讲过了,这里不多说。value
我直接赋值为FunTester
。
请注意,jq
表达式中,要想构建新的JSON
格式数据,如果key
为表达式时,需要用()
括起来,但是value
是表达式的时候就不用了,仅限于单表达式,下面会介绍一些复合表达式不适用。下面这个例子演示value
的值是表达式的时候。
fv@FunTester � ~/Downloads � cat FunTester.json | jq '{(.article[0].title): .article}'
{
"ApiTest": [
{
"author": "tester1",
"title": "ApiTest"
},
{
"author": "tester2",
"title": "performanceTest"
}
]
}
下面介绍一下map
函数,map
函数用于通过提取某个节点下的某个value
值集合来组成新的数组。
✘ fv@FunTester � ~/Downloads � cat FunTester.json | jq '{(.article[0].title): (.article | map(.title))}'
{
"ApiTest": [
"ApiTest",
"performanceTest"
]
}
我们再通过一个实验来探索一下map
函数的用法:
fv@FunTester � ~/Downloads � cat FunTester.json | jq '{(.article[0].title): (.article | map("FunTester1","FunTester2"))}'
{
"ApiTest": [
"FunTester1",
"FunTester2",
"FunTester1",
"FunTester2"
]
}
这里我将map
函数中的参数写成了两个常量,最终的输出结果是两遍的常量,所以map
函数执行了两遍,是跟前面的数组的长度一致的,而且没有去重功能。
接下来分享另外一个函数join
,这个跟Java
中拼接字符串的StringUtils.join()
非常相似。下面是Java
用的使用Demo
。
public static String join(String text, String separator) {
return StringUtils.join(ArrayUtils.toObject(text.toCharArray()), separator);
}
下面是jq
中join
函数的使用:
fv@FunTester � ~/Downloads � cat FunTester.json | jq '{(.article[0].title): (.article | map("FunTester1","FunTester2") | join("-"))}'
{
"ApiTest": "FunTester1-FunTester2-FunTester1-FunTester2"
}
我用连接符,将刚才使用map
函数构建的数组连接起来。