文章目录
- 1. JSON数据格式详解
- 1.1 两种结构
- 1.2 使用范例
- 2. jq
- 2.1 安装
- 2.2 jq 基础使用
- 2.2.1 基本语法
- 2.2.2 基础使用
- 2.2.2.1 测试环境准备
- 2.2.2.2 基础字段解析
- 2.2.2.3 列表、迭代器、管道
- 2.2.2.4 复杂数据类型构建
- 2.2.2.5 内置的操作符以及函数
- 3. python -m json.tool
1. JSON数据格式详解
JSON(JavaScript Object Notation))是一种轻量级的数据交换格式。 便于人为阅读和编写、机器解析和生成。
1.1 两种结构
- 对象:是一个无序的 key/value 键值对集合,一个对象以
{
开始,以}
结束,每个key后面跟一个:
, key/value 键值对之间使用,
分隔; - 数组:是value的有序集合,一个数组以
[
开始,以]
结束,value之间使用,
分隔;value可以是双引号内的字符串、数值、TRUE、FALSE、NULL、对象或数组;
1.2 使用范例
# 压缩
{"key1":"value1","key2":["key3","key4",{"key5":"value5","key6":"value6"}]}
# 格式化
{
"key1": "value1",
"key2": [
"key3",
"key4", {
"key5": "value5",
"key6": "value6"
}
]
}
2. jq
jq是stedolan开发的一个轻量级的和灵活的命令行JSON处理器,它主要用于在命令行界面处理JSON输入,并使用给定的过滤条件来过滤符合条件的新的JSON串。通常使用jq来进行JSON数据格式化过滤和处理。
2.1 安装
# 先安装epel源
$ yum install -y epel-release
# 再安装jq
$ yum install jq
2.2 jq 基础使用
2.2.1 基本语法
$ jq [options] <jq filter> [file...]
$ jq [options] --args <jq filter> [strings...]
$ jq [options] --jsonargs <jq filter> [JSON_TEXTS...]
# options 可选参数列表和说明
-c 将格式化json输出为紧凑的字符串格式;
-n 使用`null`作为单个输入值;
-e 根据输出设置退出状态代码;
-s 将所有输入读取(吸取)到数组中;应用过滤器;
-r 输出原始字符串,而不是JSON文本;
-R 读取原始字符串,而不是JSON文本;
-C 为JSON输出填充颜色;
-M 单色(不要为JSON着色);
-S 在输出上排序对象的键;
--tab 使用制表符进行缩进;
--arg a v 将变量$a设置为value<v>;
--argjson a v 将变量$a设置为JSON value<v>;
--slurpfile a f 将变量$a设置为从<f>读取的JSON文本数组;
--rawfile a f 将变量$a设置为包含<f>内容的字符串;
--args 其余参数是字符串参数,而不是文件;
--jsonargs 其余的参数是JSON参数,而不是文件;
-- 终止参数处理;
# 查看更多使用指南。
$ jq --help
2.2.2 基础使用
2.2.2.1 测试环境准备
$ mkdir json
$ cd json/
$ echo '{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"pc-deployment","namespace":"dev"},"spec":{"replicas":3,"selector":{"matchLabels":{"app":"nginx-pod"}},"template":{"metadata":{"labels":{"app":"nginx-pod"}},"spec":{"containers":[{"name":"nginx","image":"nginx:1.17.1","ports":[{"containerPort":80}]}]}}}}' > ./test.json
2.2.2.2 基础字段解析
# 使用.参数默认格式化整个json数据
$ cat test.json | jq . # 单独出现的"."可以省略
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "pc-deployment",
"namespace": "dev"
},
"spec": {
"replicas": 3,
"selector": {
"matchLabels": {
"app": "nginx-pod"
}
},
"template": {
"metadata": {
"labels": {
"app": "nginx-pod"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:1.17.1",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}
}
# 使用.$key来获取指定value
$ cat test.json | jq .apiVersion
"apps/v1"
# 解析json中的层级数据
$ cat test.json | jq .spec
{
"replicas": 3,
"selector": {
"matchLabels": {
"app": "nginx-pod"
}
},
"template": {
"metadata": {
"labels": {
"app": "nginx-pod"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:1.17.1",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}
# 仅输出某个层级下的数据
$ cat test.json | jq .spec.selector.matchLabels.app
"nginx-pod"
# 获取多个字段 (使用'.filed1,.filed2' 可以获取两个字段)
$ cat test.json | jq .spec.selector.matchLabels.app,.spec.template.metadata.labels.app,.spec.template.spec.containers[].ports[].containerPort
"nginx-pod"
"nginx-pod"
80
2.2.2.3 列表、迭代器、管道
# 解析json中的数组或者列表
$ cat test.json | jq .spec.template.spec.containers
[
{
"name": "nginx",
"image": "nginx:1.17.1",
"ports": [
{
"containerPort": 80
}
]
}
]
# 支持索引检查,比如.array[index],索引从0开始,-n为倒数第n个元素
$ cat test.json | jq .spec.template.spec.containers[0]
{
"name": "nginx",
"image": "nginx:1.17.1",
"ports": [
{
"containerPort": 80
}
]
}
# 支持索引范围检查,比如.array[index_src:index_dst]
cat test.json | jq .spec.template.spec.containers[0:3]
[
{
"name": "nginx",
"image": "nginx:1.17.1",
"ports": [
{
"containerPort": 80
}
]
}
]
# value迭代器.[],[]为全部范围,此时可以省略
$ cat test.json | jq .spec.template.spec.containers[]
{
"name": "nginx",
"image": "nginx:1.17.1",
"ports": [
{
"containerPort": 80
}
]
}
# 管道,在jq的表达式中,可以使用管道符号"|"来对前面的表达式结果进行再次处理
$ cat test.json | jq '.spec.template.spec.containers[]|.name'
"nginx"
# 使用管道符合时必须使用引号,否则Linux会识别为命令
$ cat test.json | jq .spec.template.spec.containers[]|.name
bash: .name: command not found...
# 值的计算
echo '{"num":12}' | jq '(.num +2)*1024'
14336
2.2.2.4 复杂数据类型构建
- 列表 (数组) 构建
[]
: 可以将输出字符返回成一个列表 (可以结合多字段使用) - 对象构建
{}
: 可以联合()
构建新的 json 对象
-
{}
可以通过字段构建新的 json 结构,比如{user, title: .titles[]}
表示将 titles 数组中的元素迭代出来后和 user 字段重新组成多个 json 字串 -
()
可以用于直接将 value 作为 key,比如{(.user): .titles}
可以直接构建无声明 key 的 json 串
- 递归下降
..
: 可以递归下降,将字符串的每一个 value 都迭代出来,用法和内置的 recurse 函数相似
# 数组构建
$ cat test.json | jq '[.spec.selector]'
[
{
"matchLabels": {
"app": "nginx-pod"
}
}
]
$ cat test.json | jq [.spec.replicas,.spec.template.metadata.labels.app]
[
3,
"nginx-pod"
]
# 批量计算
$ echo '{"num": [1,2,3,4]}' | jq '[.num[] | . * 2 ]'
[
2,
4,
6,
8
]
# 对象构建
$ cat test.json | jq '{apiVersion,kind,name:.spec.template.spec.containers[].name,image:.spec.template.spec.containers[].image}'
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"name": "nginx",
"image": "nginx:1.17.1"
}
# 构建无声明key的json数据,key = (.kind)
$ cat test.json | jq '{apiVersion,name:.spec.template.spec.containers[].name,(.kind):.spec.template.spec.containers[].image}'
{
"apiVersion": "apps/v1",
"name": "nginx",
"Deployment": "nginx:1.17.1"
}
# 递归下降,使用..可以将全部的子串解析出来,直到最后的叶子value
$ echo '[[{"a":1}]]' | jq '.. '
[
[
{
"a": 1
}
]
]
[
{
"a": 1
}
]
{
"a": 1
}
1
# 递归下降获取具体的值'.. | .filed',获取key包含a的值
$ echo '[[{"a":1}]]' | jq '.. | .a?'
1
2.2.2.5 内置的操作符以及函数
+
:两个过滤器相加,支持Numbers、Arrays、Strings、Objects类型;-
:相减,用法同上;*
,/
,%
:乘除余运算;length
:获取不同类型值的长度,支持string,array,object,null(zero);utf8bytelength
:utf8的字节长度;keys
,keys_unsorted
: 获取最外层的key以及排序之后的key,如果是列表或者数组,将返回索引;has(key)
:返回json中是否包含key,或者数组/
列表中是否包含索引下标(需要注意的是,如果需要解析
析数组/
列表内部的子串是否包含某个key,需要先使用map函数;in(object)
: 判断json中是否包含object中给定的key;max(x)
,map_values(x)
: 使用过滤器x对输入数组的元素进行挨个计算,并返回新数组;后者是给值进行计算;path(path_expression)
: 输出给定路径表达式中的数组表示;del(path_expression)
: 删除路径表达式中的filed;getpath(PATHS)
: 获取指定路径的索引;setpath(PATHS; VALUE)
: 给指定路径设置新的值;delpaths(PATHS)
: 删除指定路径;to_entries
,from_entries
,with_entries
: 二次处理 json 实体,比如从[{key:k1,value: v1}
,{key:k2,value:v2} ]
转换成{k1:v1,k2:v2}
;select(boolean_expression)
:使用bool表达式进行条件过滤;arrays
,objects
,iterables
,booleans
,numbers
,normals
,finites
,strings
,nulls
,values
,scalars
:分别只选择数组、对象、可迭代对象 (数组或对象)、布尔值、数字、普通数字、有限数字、字符串、空值、非空值和不可迭代对象的输入;add
: 过滤器 add 接受一个数组作为输入,并将数组的元素加在一起作为输出。这可能意味着根据输入数组元素的类型进行求和、连接或合并 —— 规则与上面描述的+
运算符的规则相同;any
,all
:从数组或者列表中判断是否存在或者全部存在;range
:对象生成器;floor
:输出数字的低阶值;sqrt
:求开方;tonumber
:字符串转数字;tostring
:数字转字符串;type
: 获取元素类型;sort
,sort_by(path_expression)
:排序;unique
,unique_by(path_exp)
:去重;reverse
:反转;contains(element)
:判断是否包含;startswith(str)
:判断前缀;endswith(str)
:判断后缀;split(str)
:字符串转列表;join(str)
:列表转字符串;while(cond; update)
:条件判断;until(cond; next)
:条件判断;(foo)
:引用 foo 的值;tojson
,fromjson
:从原始字符串转到 json 或者从 json 转到原始字符串;@base64
,@base64d
:base64 编码和解码;@uri
,@csv
:生成 uri,以及表格格式。
# keys
$ cat test.json | jq 'keys'
[
"apiVersion",
"kind",
"metadata",
"spec"
]
# keys_unsorted
$ cat test.json | jq 'keys_unsorted'
[
"apiVersion",
"kind",
"metadata",
"spec"
]
# has
$ cat test.json | jq '.spec | has("replicas")'
true
$ cat test.json | jq 'has("replicas")'
false
$ cat test.json | jq 'has("spec")'
true
# to_entries, from_entries, with_entries
$ cat test.json | jq '.spec | to_entries'
[
{
"key": "replicas",
"value": 3
},
{
"key": "selector",
"value": {
"matchLabels": {
"app": "nginx-pod"
}
}
},
{
"key": "template",
"value": {
"metadata": {
"labels": {
"app": "nginx-pod"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:1.17.1",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}
]
# select(bool_exp)
$ cat test.json | jq '. | select(.kind == "Deployment")'
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "pc-deployment",
"namespace": "dev"
},
"spec": {
"replicas": 3,
"selector": {
"matchLabels": {
"app": "nginx-pod"
}
},
"template": {
"metadata": {
"labels": {
"app": "nginx-pod"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:1.17.1",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}
}
# @base64/@base64d
$ cat test.json | jq '.apiVersion '
"apps/v1"
$ cat test.json | jq '.apiVersion | @base64'
"YXBwcy92MQ=="
$ cat test.json | jq '.apiVersion | @base64 | @base64d'
"apps/v1"
3. python -m json.tool
若Linux系统无法下载jq工具,可以使用默认python工具包中的json.tool做JSON数据格式化操作(部分操作系统使用的是python3版本),与等同于jq -M
不着色显示。
$ cat test.json | python -m json.tool
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "pc-deployment",
"namespace": "dev"
},
"spec": {
"replicas": 3,
"selector": {
"matchLabels": {
"app": "nginx-pod"
}
},
"template": {
"metadata": {
"labels": {
"app": "nginx-pod"
}
},
"spec": {
"containers": [
{
"image": "nginx:1.17.1",
"name": "nginx",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}
}