如何用 jq 制表嵌套的 JSON 文件
How to tabulate nested JSON file with jq
我有以下 JSON 文件,我想用有人建议我的 jq 工具对其进行解析,但我是新手。有 3 parents 个节点
具有相同的 children 个名称。 parent 个节点是 MNR、GNR 和 MSNR,每个节点都有 children 个名为 N1、N2、NR_i、NR_f.
{
"Main": {
"Document": "Doc.1",
"Cini": "DDFR",
"List": {
"SubList": {
"CdTa": "ABC",
"NN": "XYZ",
"ND": {
"RiS": {
"RiN": {
"NSE14": {
"MNRs": {
"MRD": [
{
"NR": {
"N1": "393",
"N2": "720",
"SNR": {
"NR_i": "203",
"NR_f": "49994"
}
}
},
{
"NR": {
"N1": "687",
"N2": "345",
"SNR": {
"NR_i": "55005",
"NR_f": "1229996"
}
}
}
]
},
"GNRs": {
"RD": {
"NR": {
"N1": "649",
"N2": "111",
"SNR": {
"NR_i": "55400",
"NR_f": "877"
}
}
}
},
"MSNRs": {
"NR": [
{
"N1": "748",
"N2": "5624",
"SNR": {
"NR_i": "8746",
"NR_f": "7773"
}
},
{
"N1": "124",
"N2": "54",
"SNR": {
"NR_i": "8847",
"NR_f": "5526"
}
}
]
}
},
"NSE12": {
"MBB": "990",
"MRB": "123"
},
"MGE13": {
"TBB": "849",
"TRB": "113"
}
}
}
}
}
}
}
}
通过这段代码,我得到以下结果
.Main.List.SubList.ND.RiS.RiN.NSE14.MNRs.MRD
[
{
"NR": {
"N1": "393",
"N2": "720",
"SNR": {
"NR_i": "203",
"NR_f": "49994"
}
}
},
{
"NR": {
"N1": "687",
"N2": "345",
"SNR": {
"NR_i": "55005",
"NR_f": "1229996"
}
}
}
]
通过这些命令,我得到了每个 children 和其他 null 的单个值的列。
.. | .N1?
.. | .N2?
.. | .NR_i?
.. | .NR_f?
我离我想要的输出还很远,因为我想为每个 parent 提取 children 并在
下面的表格。
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| MNRs | GNRs | MSNRs |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| N1 | N2 | NR_i | NR_f | N1 | N2 | NR_i | NR_f | N1 | N2 | NR_i | NR_f |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| 393 | 720 | 203 | 49994 | 649 | 111 | 55400 | 877 | 748 | 5624 | 8746 | 7773 |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| 687 | 345 | 55005 | 1229996 | | | | | 124 | 54 | 8847 | 5526 |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
有人可以帮我解决这个问题吗?提前致谢。
由于输入 JSON 的性质仅通过示例给出,让我们首先定义一个用于线性化 .NR
:
的过滤器
# Produce a stream of arrays
def linearize:
if type == "array" then .[] | linearize
else [ .N1, .N2, .SNR.NR_i, .SNR.NR_f]
end;
现在可以在保留 top-level 组的同时提取相关数据,如下所示:
.Main.List.SubList.ND.RiS.RiN.NSE14
| [to_entries[]
| [.key]
+ [.value | .. | objects | select(has("NR")) | .NR | [ linearize ]] ]
因为输入 JSON 不统一,通过使用以下映射扩充上述管道将有助于确保统一性:
| map(if length > 2 then [.[0], [.[1:][][]]] else . end)
这会生成一个结构如下的 JSON 数组:
[["MNRs",[["393","720","203","49994"]],[["687","345","55005","1229996"]]],
["GNRs", ...
要从此中间结果获得 table 的第一行数据,值得定义一个函数来提供必要的填充:
def row($i; $padding):
. as $in
| [range(0;$padding) | null] as $nulls
| reduce range(0; length) as $ix
([]; . + ($in[$ix][1][$i] // $nulls));
现在第一行数据可以通过row(0;4)获取,第二行通过row(1;4)等获取
通过map(.[1] | length) | max
过滤中间数据结构得到数据行总数;因此,可以通过将以下内容附加到先前的管道来获得数据行:
| (map(.[1] | length) | max) as $rows
| range(0; $rows) as $r
| row($r; 4)
| @tsv
使用 -r command-line 选项和给定的样本,输出将是:
393 720 203 49994 649 111 55400 877 748 5624 8746 7773
687 345 55005 1229996 124 54 8847 5526
添加 headers 留作练习:-)
我有以下 JSON 文件,我想用有人建议我的 jq 工具对其进行解析,但我是新手。有 3 parents 个节点 具有相同的 children 个名称。 parent 个节点是 MNR、GNR 和 MSNR,每个节点都有 children 个名为 N1、N2、NR_i、NR_f.
{
"Main": {
"Document": "Doc.1",
"Cini": "DDFR",
"List": {
"SubList": {
"CdTa": "ABC",
"NN": "XYZ",
"ND": {
"RiS": {
"RiN": {
"NSE14": {
"MNRs": {
"MRD": [
{
"NR": {
"N1": "393",
"N2": "720",
"SNR": {
"NR_i": "203",
"NR_f": "49994"
}
}
},
{
"NR": {
"N1": "687",
"N2": "345",
"SNR": {
"NR_i": "55005",
"NR_f": "1229996"
}
}
}
]
},
"GNRs": {
"RD": {
"NR": {
"N1": "649",
"N2": "111",
"SNR": {
"NR_i": "55400",
"NR_f": "877"
}
}
}
},
"MSNRs": {
"NR": [
{
"N1": "748",
"N2": "5624",
"SNR": {
"NR_i": "8746",
"NR_f": "7773"
}
},
{
"N1": "124",
"N2": "54",
"SNR": {
"NR_i": "8847",
"NR_f": "5526"
}
}
]
}
},
"NSE12": {
"MBB": "990",
"MRB": "123"
},
"MGE13": {
"TBB": "849",
"TRB": "113"
}
}
}
}
}
}
}
}
通过这段代码,我得到以下结果
.Main.List.SubList.ND.RiS.RiN.NSE14.MNRs.MRD
[
{
"NR": {
"N1": "393",
"N2": "720",
"SNR": {
"NR_i": "203",
"NR_f": "49994"
}
}
},
{
"NR": {
"N1": "687",
"N2": "345",
"SNR": {
"NR_i": "55005",
"NR_f": "1229996"
}
}
}
]
通过这些命令,我得到了每个 children 和其他 null 的单个值的列。
.. | .N1?
.. | .N2?
.. | .NR_i?
.. | .NR_f?
我离我想要的输出还很远,因为我想为每个 parent 提取 children 并在 下面的表格。
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| MNRs | GNRs | MSNRs |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| N1 | N2 | NR_i | NR_f | N1 | N2 | NR_i | NR_f | N1 | N2 | NR_i | NR_f |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| 393 | 720 | 203 | 49994 | 649 | 111 | 55400 | 877 | 748 | 5624 | 8746 | 7773 |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
| 687 | 345 | 55005 | 1229996 | | | | | 124 | 54 | 8847 | 5526 |
+------+------+-------+---------+-----+-----+-------+------+-----+------+------+------+
有人可以帮我解决这个问题吗?提前致谢。
由于输入 JSON 的性质仅通过示例给出,让我们首先定义一个用于线性化 .NR
:
# Produce a stream of arrays
def linearize:
if type == "array" then .[] | linearize
else [ .N1, .N2, .SNR.NR_i, .SNR.NR_f]
end;
现在可以在保留 top-level 组的同时提取相关数据,如下所示:
.Main.List.SubList.ND.RiS.RiN.NSE14
| [to_entries[]
| [.key]
+ [.value | .. | objects | select(has("NR")) | .NR | [ linearize ]] ]
因为输入 JSON 不统一,通过使用以下映射扩充上述管道将有助于确保统一性:
| map(if length > 2 then [.[0], [.[1:][][]]] else . end)
这会生成一个结构如下的 JSON 数组:
[["MNRs",[["393","720","203","49994"]],[["687","345","55005","1229996"]]],
["GNRs", ...
要从此中间结果获得 table 的第一行数据,值得定义一个函数来提供必要的填充:
def row($i; $padding):
. as $in
| [range(0;$padding) | null] as $nulls
| reduce range(0; length) as $ix
([]; . + ($in[$ix][1][$i] // $nulls));
现在第一行数据可以通过row(0;4)获取,第二行通过row(1;4)等获取
通过map(.[1] | length) | max
过滤中间数据结构得到数据行总数;因此,可以通过将以下内容附加到先前的管道来获得数据行:
| (map(.[1] | length) | max) as $rows
| range(0; $rows) as $r
| row($r; 4)
| @tsv
使用 -r command-line 选项和给定的样本,输出将是:
393 720 203 49994 649 111 55400 877 748 5624 8746 7773
687 345 55005 1229996 124 54 8847 5526
添加 headers 留作练习:-)