文章目录
- 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 安装
$ 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}]}]}}}
}