[英]How to get keys and key types of nested json using jq
我有一个像下面这样的文件 data.json -
{
"parameter": {
"colA": "No",
"COLB": "No"
},
"workRequired": 0,
"work": 0,
"updateType": "AUTO"
}
我知道如何获取 json 的密钥和密钥类型 -
jq -c 'to_entries[] | [.key, (.value|type)]' data.json
但上面的命令返回我 -
["parmeter","object"]
["workRequired","string"]
["work","null"]
["updateType","number"]
但我希望命令像下面一样返回,以便我获得嵌套 json 的键类型 -
["parmeter"."colA","string"]
["parmeter"."colB","string"]
["workRequired","string"]
["work","null"]
["updateType","number"]
有什么办法可以使用jq
这非常接近请求的输出。
jq -c 'to_entries[]
| if .value|type == "object"
then .key as $k
| .value
| to_entries[]
| ["\($k).\(.key)", (.value|type)]
else [.key, (.value|type)]
end'
输出:
["parameter.colA","string"]
["parameter.COLB","string"]
["workRequired","number"]
["work","number"]
["updateType","string"]
主要区别在于前两行。 我不认为["parameter"."colA","string']
是有效的 json。
有些类型也不同。
解释
了解这些东西如何工作的一种方法是一步一步地学习。 所以从jq -c 'to_entries[]'
,看看结果是什么,然后依次添加每个步骤。 说明书也很不错。
在这里,我们从一个对象开始。 第一个命令是to_entries[]
。 引用手册,当“to_entries 被传递一个对象,然后对于输入中的每个 k: v 条目,输出数组包含 {"key": k, "value": v}。” 在末尾添加[]
意味着输出将只是to_entries
生成的数组中的对象。 所以这是第一步后的输出:
{"key":"parameter","value":{"colA":"No","COLB":"No"}}
{"key":"workRequired","value":0}
{"key":"work","value":0}
{"key":"updateType","value":"AUTO"}
现在我们有四个对象。 一个包含另一个对象。 原始问题涉及包含对象的对象。 问题是在最终输出中将包含对象的键与包含对象的键组合在一起。
条件if .value|type == "object"
标识包含对象的对象。
当满足此条件时, .key as $k
将包含对象的“key”键的值保存为名为 $k 的变量。
然后我们用包含的对象重复to_entries[]
。 包含对象是包含对象中键“值”的值。 代码.value | to_entries[]
.value | to_entries[]
通过to_entries[]
过滤包含的对象。 这给了我们这两个对象。
{"key":"colA","value":"No"}
{"key":"COLB","value":"No"}
要创建所需的输出,我们需要构造一个数组,该数组将保存为 $k 的包含对象的键与这两个对象的元素组合在一起。 这是我们如何做到这一点。 (有关引号中的部分如何工作的说明,请参阅手册中的“字符串插值”。)
["\($k).\(.key)", (.value|type)]
对于每个对象,我们保存为变量 $k 的键与对象中“键”键的值组合在一起。 然后我们输出对象中“value”键的值的类型。
这产生了最终输出的前两行:
["parameter.colA","string"]
["parameter.COLB","string"]
现在我们转到条件的另一个分支。 这将处理第一步中不包含对象的三个对象。 在这里,我们只是重复问题中的原始代码,因为这是令人满意的。
else [.key, (.value|type)]
这产生了:
["workRequired","number"]
["work","number"]
["updateType","string"]
命令end
结束条件。
还有一件事。 一开始的标志-c
告诉 jq 我们想要紧凑的输出。 没有它,输出在逻辑上是相同的,但分布在多行上。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.