处理JSON最强命令jq使用场景
作者:2021不再有雨
史上最全jq命令使用详解
一. 前言
本文价值千金, 阅读前请先收藏.
jq命令
是处理json字符串的神器, 主要用于获取JSON属性/简单重组JSON字符串.
本章将详细介绍jq的主要应用场景, 帮助大家在平时工作中处理JSON的效率大大提升.
二. 语法
jq本身有一套完整语法,如要详细掌握参考另外一篇总结 jq详细语法参考
1. 使用语法
jq 表达式 处理源
处理源
可以为文件路径或管道: 读取后必须为JSON对象
, JSON数组
, JSON对象流
三类
2. 概念理解
JSON对象
以{
开头, 以}
结尾的JSON字符串, 形如{}
示例:
{ "productId": "2048200008352211", "productName": "COACH蔻驰佩利系列 马车标识米兰编织链石英表" }
JSON数组
以[
开头, 以]
结尾的JSON字符串, 元素间用,
分隔包括基本数组和JSON对象数组, 形如[{},{},{}]
基本数组: 元素为基本数据类型, 如[1,2,3,5], [“shanghai”, “guangzhou”,“beijing”]JSON对象数组: 元素为JSON对象, 略
JSON对象流
- 常规的JSON定义没有这种结构, 是jq命令支持的一种字符串结构类型
- 概念名字是我自己随便起的, 主要是方便理解
- JSON对象流和JSON数组有点类似: 是指多个连续的JSON对象组成的字符串, 没有[开头, 没有]结尾, 且元素间没有分隔符或以空格/换行来分隔, 形如{}{}{}, 示例如下:
- 特殊地, JSON对象流也可以是基本属性流, 如"a" "b" "c", 1 2 3
- 有些情况下JSON对象流无法转换成JSON数组, 通过sed命令转换
- jq '.' | sed 's/^\}/\},/' | sed '1c \[{' | sed '$c \}]'
{ "productId": "2048200008352211", "productName": "COACH蔻驰佩利系列 马车标识米兰编织链石英表" } { "productId": "2048200008352212", "productName": "COACH蔻驰佩利系列 马车标识米兰编织链石英表2" } { "productId": "2048200008352213", "productName": "COACH蔻驰佩利系列 马车标识米兰编织链石英表3" }
根对象
是指jq
命令当前处理的处理源
的表达式引用, 在表达式中用.
来表示
表达式/路径
jq
命令是基于表达式输出结果的, 表达式可以通过.
来访问子属性或子对象表达式的语法, 类似ognl表达式(对象导航语言)如.order.address.city
表示获取当前处理源
order(子对象)下的address(子对象)的city
属性
{ "uid": 11603, "mobile": "172****1333", "order": { "address": { "province": "上海市", "city": "海市", "distict": "浦东新区", "line": "广兰路地铁站1号口" }, "items": [ { "itemId": 123, "itemName": "无人机1" }, { "itemId": 124, "itemName": "无人机2" } ] } }
三. 主要用法
本文示例文件json.txt, 在文章最后
1. 常见表达式含义
.
: 放在表达式开头, 用来表示.
根对象, 也可用在属性之间作为访问路径的连接
.name
: 输出指定属性,使用.
连接的路径访问字段, 路径可用多层, 如order.items[0].itemId
.[下标]
: 输出单个指定index的数组元素(从0开始)
.[下标1,下标2,..]
: 输出多个指定数组元素, 结果为JSON对象流
express[]
: 表达式express
为JSON数组
, 后面跟[]
表示将express
表示的JSON对象数组
转换成JSON对象流
, 形如:[{},{},{}]
转换成{}{}{}
[表达式]
: 将JSON对象流
组合成JSON对象数组
,形如:{}{}{}
组装成[{},{},{}]
,
:需要输出多个表达式的结果用来拼接各表达式, 如jq '.name,.address.city' json.txt
|
: 管道, 相对于运行两次jq
命令, 前jq运行结果作为后jq的处理源
根据前jq的运行结果数据类型分为:- JSON对象: 可简化, 如
jq '.[0]|.address' json.txt
和jq '.[0].address' json.txt
- JSON对象数组: 后置表达式只能用内置函数, 如
jq '.[0].arrayBrowser|length' json.txt
- JSON对象流: 相当于对每个元素都运行后置表达式, 整体结果还是
JSON对象流
,如jq '.[0].arrayBrowser[]|.name' json.txt
注意:
要想对
JSON对象数组
每个元素进行处理, 必须先转换成JSON对象流
2. 基本使用场景
jq '.' json.txt
– 格式化
jq '.[0].address.city' json.txt
--获取指定字段的值(可嵌套)
jq '.[0].name,.[0].url' json.txt
--使用逗号分隔,取多个字段的值;返回值以换行分隔
jq '.[0].arrayBrowser[0]' json.txt
--提取数组的单个元素
jq '.[0].arrayBrowser[0,1]' json.txt
--提取数组的多个元素
jq '.[0].arrayBrowser[]' json.txt
– 提取数组的全部元素转换成JSON对象流
jq '[.data.results[]|{topicId,viewCount}]' hjsource.json
– 提取数组的指定属性
jq '[.data.results[]|{id:topicId,count:viewCount}]' hjsource.json
– 提取数组的指定属性并重命名
注意:
上述最后两个示例先将
JSON对象数组
转化成JSON对象流
, 再对各元素进行处理, 再组装成JSON对象数组
3. 重组
场景: 重组成对象
使用方法一: 组装时仅复用value
jq '{simpleName:.[0].name,postUrl:.[0].url}' json.txt
, 得到结果 :
{
"simpleName": "脚本之家",
"postUrl": "//www.jb51.net"
}
比较下和jq '.[]|{simpleName:.name,postUrl:.url}' json.txt
的区别.
(前者处理单个对象, 后者处理JSON对象流
)
2.使用方法二: 组装时复用整个key-value
运行jq '.[0]|{name,url}' json.txt
, 得到结果:
{
"name": "脚本之家",
"url": "//www.jb51.net"
}
比较下和 jq '.[]|{name,url}' json.txt
的区别.
(前者处理单个对象, 后者处理JSON对象流
)
注意:
引用的key-value可以是基本属性节点, 也可以是对象节点.
如运行
jq '.[0]|{name,address}' json.txt
复用key-value时表达式前面没有
.
前缀, 仅复用value时才有.
前缀用
,
分隔的多个表达式没必要任何关系, 层次也可不一样
场景: 重组成数组
在表达式外边套上[]
, 即可组装成数组. 根据组合元素的不同, 可以分以下三类:
- 重组的元素可以是基本属性, 组合结果是组装成基本属性的数组
- 重组的元素可以是单个json对象, 组合结果是在外面套个数组结果
- 重组的元素可以是单个JSON对象流, 组合结果是转化成JSON对象数组
- 有些情况下JSON对象流无法转换成JSON数组, 通过sed命令转换
- jq '.' | sed 's/^\}/\},/' | sed '1s/.*/\[\{/' | sed '$s/.*/\}\]/
1.重组元素为基本属性
运行 jq '[.[0].name,.[0].url]' json.txt
, 得到结果:
[
"脚本之家",
"//www.jb51.net"
]
2.重组元素为单个json对象
运行 jq '[.[0].address]' json.txt
, 得到结果:
[
{
"city": "厦门",
"country": "中国"
}
]
运行 jq '[.[0].arrayBrowser]' json.txt
, 得到结果:
[
[
{
"name": "Google",
"url": "http://www.google.com"
},
{
"name": "Baidu",
"url": "http://www.baidu.com"
}
]
]
3.重组元素为JSON对象流
jq '[.[]|.arrayBrowser[]]' json.txt
, 得到结果:
[
{
"name": "Google",
"url": "http://www.google.com"
},
{
"name": "Baidu",
"url": "http://www.baidu.com"
},
{
"name": "360",
"url": "http://www.so.com"
},
{
"name": "bing",
"url": "http://www.bing.com"
}
]
4. 管道的使用
管道|
的作用, 把管道前的处理结果作为管道后面处理的输入. 相当于管道前后各运行一次jq
命令. (管道可以多次使用)
用法和前面的没有区别. 略
5. 内置函数的使用获取json对象的所有key组成的数组
命令格式: jq keys
, 表达式只能是keys
, 不能包含其他语法, 如果需要获取嵌套对象keys, 通过管道即可.
运行 jq '.[0]|keys' json.txt
, 得到结果:
[
"address",
"arrayBrowser",
"name",
"url"
]
获取length
命令格式: jq length
, 表达式只能是length
, 不能包含其他语法, 如果需要获取嵌套对象length, 通过管道即可.
如果处理对象是基本属性, 则length返回其字符个数. 如
jq '.[0].name|length' json.txt
, 结果为4
.如果处理对象是json对象, 则length返回其属性个数. 如
jq '.[0].address|length' json.txt
, 返回2
.如果处理对象是数组, 则length返回数组的长度. 如
jq '.[0].arrayBrowser|length' json.txt
, 得到2
.
删除某属性
命令格式: jq del(属性表达式)
, 一般结合管道使用
该属性可以是基本属性, 或json对象, 或数组
运行 jq '.[0]|del(.address)|del(.arrayBrowser)' json.txt
, 得到结果:
{
"name": "脚本之家",
"url": "//www.jb51.net"
}
设置元素值
命令格式: jq 属性表达式=新的值'
, 一般结合管道使用
新的值
可以是基本属性, json对象, 数组.(双引号不能省略)
运行 jq '.[0]|.name="myTool"' json.txt
, 得到结果:
{
"name": "jb51",
"url": "//www.jb51.net",
"address": {
"city": "厦门",
"country": "中国"
},
"arrayBrowser": [
{
"name": "Google",
"url": "http://www.google.com"
},
{
"name": "Baidu",
"url": "http://www.baidu.com"
}
]
}
增加属性
命令格式: jq 属性表达式+{新的节点}
, 一般结合管道使用
其中属性表达式
的结果必须为对象
新的节点
只能是基本属性, 不能是对象, 数组.
运行jq '.[0].address+{version:"1.0"}' json.txt
, 得到结果:
{
"city": "厦门",
"country": "中国",
"version": "1.0"
}
判断是否有某属性
jq '.[0]|has("name")' json.txt
, 返回结果为true
jq '.[]|.arrayBrowser[]|has("name")' json.txt
#判断单个属性
jq '.[]|.arrayBrowser[]|{a:has("sign"),b:has("name")}' json.txt
#判断多个属性并组装成JSON对象
- 其中属性要用
""
包裹 - 只能判断子属性, 不能判断后代属性
- 处理源可以为
JSON对象
和JSON对象流
四. 示例文件json.txt
[ { "name": "脚本之家", "url": "http://jb51.net", "address": { "city": "厦门", "country": "中国" }, "arrayBrowser": [ { "name": "Google", "url": "http://www.google.com" }, { "name": "Baidu", "url": "http://www.baidu.com" } ] }, { "name": "脚本之家", "url": "http://jb51.net", "address": { "city": "大连", "country": "中国" }, "arrayBrowser": [ { "name": "360", "url": "http://www.so.com" }, { "name": "bing", "url": "http://www.bing.com" } ] } ]
到此这篇关于处理JSON最强命令jq使用详解的文章就介绍到这了,更多相关JSON命令jq使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!