简介
JSON 是前后端交互经常用到的格式,对于常见后端语言来说(比如 Java、Python、Golang 等),解析 JSON 都不是什么大事,干的相当的漂亮。Linux 下也有处理处理 JSON 的神器:jq
。
要使用 jq
首先需要安装它,由于它是使用 C 语言编写的,所以它没有什么特殊依赖,它对应命令的名字也叫 jq
,所以你可以直接在官网下载它的二进制包加个执行权限就可以使用了,官网地址:
可以看到其它安装方式在上述链接中也描述的很全面,我这里使用的 Linux 发行版是 Ubuntu,所以安装它我也可以使用 apt
:
$ apt install jq -y
jq
提供了类是于编程语言的表达式系统,包括逻辑判断、正则表达式、debug、try-catch、while、以及各种函数等等,可以作为一门语言来学,这里就不详细展开来,换言之就是它很牛批内容很多,所以本篇文章仅会介绍一些我觉得常用、有必要知道的知识点,所以你如果想要了解除本篇文章之外的内容,你可以参考官网:
使用
首先准备以下 json 数据用做测试,我这里将如下内容保存到名为 json-example.json
文件中 :
{"apiVersion": "extensions/v1beta1","kind": "Ingress","metadata": {"annotations": {"kubernetes.io/ingress.class": "nginx"},
"generation": 1,"name": "test-ing","namespace": "test"},"spec": {"rules": [{"host": "zze.xyz",
"http": {"paths": [
{"backend": {"serviceName": "zze-backend","servicePort": 80},"path": "/","pathType": "ImplementationSpecific"},{"backend": {"serviceName": "test-backend","servicePort": 80
},"path": "/test","pathType": "ImplementationSpecific"}]}}]}}
你可能会想我为啥要放一个乱糟糟的未排版的内容在这,因为这里要介绍的 jq
的第一个功能就是格式化排版。
它的使用类似 grep|awk|sed
,既支持 jq <选项|表达式> <文件名>
的语法,也支持接收管道过来的数据,所以这里也可以使用 cat <文件名> | jq [选项|表达式]
的语法。
在 jq
的表达式中,开头的 .
有着特殊含义。可以把整个 Json 内容当做一个大的 Object,而 .
就代指这个 Object,其中的各个 Key 就是这个 Object 的属性,属性可以通过 .<属性名>[.属性名[.属性名]...]
的方式来访问。
格式化排版
- 格式化显示
json-example.json
的内容。
# 也可使用 `cat json-example.json | jq`,后面的 `'.'` 可以省略,这里它的语法有点类似 Go Template 的语法,如果你常写 Helm Chart 就应该感到很亲切。
$ cat json-example.json | jq '.'
{
"apiVersion": "extensions/v1beta1",
"kind": "Ingress",
"metadata": {
"annotations": {
"kubernetes.io/ingress.class": "nginx"
},
"generation": 1,
"name": "test-ing",
"namespace": "test"
},
"spec": {
"rules": [
{
"host": "zze.xyz",
"http": {
"paths": [
{
"backend": {
"serviceName": "zze-backend",
"servicePort": 80
},
"path": "/",
"pathType": "ImplementationSpecific"
},
{
"backend": {
"serviceName": "test-backend",
"servicePort": 80
},
"path": "/test",
"pathType": "ImplementationSpecific"
}
]
}
}
]
}
}
按 key 取值
- 取出
metadata.namespace
值。
$ cat json-example.json | jq '.metadata.namespace'
"test"
- 取出
spec.rules
列表下第一个元素的host
值。
# [0] 表示取列表的第一个元素,0 是元素的索引
$ cat json-example.json | jq '.spec.rules[0].host'
"zze.xyz"
- 取出
spec.rules[].http.paths
列表下所有元素的path
值。
$ cat json-example.json | jq '.spec.rules[].http.paths[].path'
"/"
"/test"
- 取一个不存在的 Key
haha
会返回null
。
$ cat json-example.json | jq '.haha'
null
修改指定 Key 的值
- 修改
metadata.namespace
的值为zze-test
。
{
...
"metadata": {
"annotations": {
"kubernetes.io/ingress.class": "nginx"
},
"generation": 1,
"name": "test-ing",
"namespace": "zze-test"
},
...
为文章简约明了,我这里只将改变后内容相关结果展示出来,
...
表示内容没有发生变化。
- 修改
spec.rules
列表下第一个元素的host
值为test.zze.xyz
。
$ cat json-example.json | jq '.spec.rules[0].host="test.zze.xyz"'
{
...
"spec": {
"rules": [
{
"host": "test.zze.xyz",
...
增加属性
- 增加一个多级嵌套属性
status.loadBalancer.ingress
,它是一个数组,该数组下还有一个嵌套对象{"ip" : "10.0.1.100"}
。
$ cat json-example.json | jq '.status.loadBalancer.ingress[0]={"ip" : "10.0.1.100"}'
...
},
"status": {
"loadBalancer": {
"ingress": [
{
"ip": "10.0.1.100"
}
]
}
}
}
取指定字段值生成新 Json
- 修改
metadata.annos
的名字为metadata.annos
并添加属性n
。
$ cat json-example.json | jq '. | {"n": .metadata.name, ".annos": .metadata.annotations}'
{
"n": "test-ing",
".annos": {
"kubernetes.io/ingress.class": "nginx"
}
}
- 修改
spec.rules[].http.paths
下所有的名为path
的 Key 为p
值不变存入新数组。
$ cat json-example.json | jq '[.spec.rules[].http.paths[] | {"p": .path }]'
[
{
"p": "/"
},
{
"p": "/test"
}
]
查看列表长度
- 查看
spec.rules
列表长度。
$ cat json-example.json | jq '.spec.rules | length'
1
删除指定 Key
- 删除
metadata.generation
属性。
$ cat json-example.json | jq 'del(.metadata.generation)'
{
"apiVersion": "extensions/v1beta1",
"kind": "Ingress",
"metadata": {
"annotations": {
"kubernetes.io/ingress.class": "nginx"
},
"name": "test-ing",
"namespace": "test"
},
...
获取所有的 Key
- 获取最外层所有 Keys。
$ cat json-example.json | jq 'keys'
[
"apiVersion",
"kind",
"metadata",
"spec"
]
- 获取
metadata
下的所有 Key
$ cat json-example.json | jq '.metadata | keys'
[
"annotations",
"generation",
"name",
"namespace"
]
判断是否存在某个 Key
- 判断
metadata
下是否存在名为generation
的 Key。
$ cat json-example.json | jq '.metadata | has("generation")'
true
评论区