后端开发的工程师经常在linux下开发,当我们拿到一个json格式的数据时,如何有效对这个数据进行分析?我们可以采用python结合json库来分析,但是linux有一个很好用的工具,让我们可以方便地处理json文本,功能非常强大。
官方文档
参考官网说明
macOS:
brew install jq
Linux
sudo apt-get install jq
jq可以把json的文本输出为可读形式,我准备了一份测试json数据,如下:
{
"name": "xueyuan",
"age": 21,
"birthday": "10th August",
"email": "[email protected]",
"skills" : [
"C/C++",
"Python",
"Golang",
"Node.js"
]
}
我使用python的json库把它处理为一个字符串,如下:
{"skills": ["C/C++", "Python", "Golang", "Node.js"], "age": 21, "birthday": "10th August", "name": "xueyuan", "email": "[email protected]"}
这个格式是我们在实际生产中经常看到的格式,比如我们使用curl请求一个接口,返回了一个json,比如我们在自己的项目中测试输出了一个json数据,这种格式往往可读性较差,我们需要进行处理后才能查看。
要转换成python处理前的那一种易读形式很简单,执行:
cat json2.data | jq '.'
#也可以写作 cat json2.data | jq .
#不加引号,但是为了标准最好写上,因为某些时候不加会有问题.
输出
jq把数据转换成易读格式,还添加了颜色高亮说明,其中key和value使用了不同的颜色。
如果json数据很大,我们只想看其中某个字段数据,那么使用如下语法:
#key是字段名称
jq '.'
当某个字段是一个列表,jq可以对其进行切片
jq '.[s:e]'
测试
切片支持图中几种格式,注意和python列表切片方式进行区分。
区别一下’.skills’和’.skills[]'两种,可以看到前者输出是一个列表,后者是非json格式的列表成员。
上一节是jq
的常用用法,这里讲解jq的具体原理。
jq从linux管道或者文件中获取文本输入,如果文本不满足json格式,那么jq会报错,可以用这个方法来检查一个文本是否满足json检查:
jq '.' json_file > /dev/null
jq使用filter来处理json文本,并输出filter处理后的内容到标准输出,filter是用来过滤满足需求的字段的,比如最简单的filter '.'
,这个表示无过滤策略,因此会输出全部json文本。
key filter
'.'
过滤满足key的字段名,输出这个key的值。
key-value filter
''
输出key和value,区别key filter,如下
因为key-value必须归属于某个对象,所以添加外层{}。
index filter
'.[index]'
'.[index1, index2]'
'.[s:e]'
'.[:e]'
'.[s:]'
'.[]'
数组索引和切片,用来操作列表元素。
嵌套层级filter
'.key1.key2.key3'
用于嵌套的json数据filter。
多个filter
'.key1, .key2, .key3'
使用英文单字节逗号分隔filter,用于在一个filter中过滤多个字段。
filter管道
'filter1 | filter2 | filter3'
example
jq '.contact | .phone | .home' people.json
由于大部分filter之后,输出仍然是一个json数据,所以可以将filter通过管道连接。
重新组织filter后输出的数据
有时候我们需要重新构造json的结构,比如去掉某一层嵌套,比如取某几个字段组成一个新的json,这时候我们需要重新改变json的结构,我们可以使用[]
和{}
来重新组织json。
#把输出组织成一个列表
jq '[filter1, filter2, filter3]' data.json
#把输出组织为新的json对象
jq '{filter1, filter2, filter3}' data.json
递归展开json结构
有时候我们需要在一个json里边查找某个字段,但是确不知道这个字段在哪个嵌套里边,如果嵌套很深那么很难找到,jq可以把嵌套展开打平之后再查找。
#展开嵌套
jq '..' data.json
length filter
计算元素长度,对于对象,length表示对象里的元素个数,对于string,length表示string字符数,对于列表,表示列表元素个数。
检查某个key是否存在
如果输入是一个对象,那么对象的元素是以"key-value"形式存在的,使用
jq 'has("key-name")' data.json
检查json对象是否含有某个key。
列表遍历
jq支持使用map()或者map_values()遍历列表,或者对象的值。
删除某个key
jq 'del(filter)' json.data
使用del()删除filter描述的key-value。
上一节只说明了jq比较常用的功能,实际上jq还有更多实用的filter,如果上述的功能还没有满足你的需求,你可以在jq项目地址上找到详细说明。