之前的文章使用 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函数构建的数组连接起来。