使用jq处理JSON数据(二)

之前的文章使用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);
    }

下面是jqjoin函数的使用:

 fv@FunTester  ~/Downloads  cat FunTester.json | jq  '{(.article[0].title): (.article | map("FunTester1","FunTester2") | join("-"))}'
{
  "ApiTest": "FunTester1-FunTester2-FunTester1-FunTester2"
}

我用连接符,将刚才使用map函数构建的数组连接起来。


FunTester腾讯云年度作者Boss直聘签约作者GDevOps官方合作媒体,非著名测试开发。