首页 > 解决方案 > 带有嵌套 JSON 的 JQ

问题描述

您好,我是 JQ 和一般命令行工具的新手,所以我真的很迷茫。我有一个 JSON 文件,格式如下:

{
    "Z": {
        "00": [{
                "e": "A000"
            }, {
                "e": "A020"
            }
        ],
        "01": [{
                "e": "A102"
            }, {
                "e": "C027"
            }
        ]
    },
    "X": {
        "00": [{
                "e": "P002"
            }, {
                "e": "T027"
            }
        ],
        "01": [{
                "e": "A003"
            }, {
                "e": "A020"
            }
        ]
    }
}

其中每个对象都是一个七字符的字母数字代码。

我正在寻找的是输出由换行符分隔的每个代码的命令,如下所示:

Z00A000
Z00A020
Z01A102
Z01C027
X00P002
X00T027
X01A003
X01A020

尽管名称“Z”和“X”以及子名称“00”“01”等可能会发生变化,因此 JSON 的格式将始终相同,因此它们不能被硬编码。

如前所述,我对此很陌生,我最接近的是

jq '.[] | .[] | .[] | .e'

这给了我代码的最后四个字符的列表。

老实说,我完全迷失了,所以任何帮助都将不胜感激。谢谢阅读。

标签: jsonkeyjq

解决方案


这是一个基于格式统一性的解决方案。

首先,让我们定义一个辅助函数来处理 JSON 对象,这些对象的值是以下形式的对象数组{"e": _}

def combine:
  keys_unsorted[] as $k
  | $k + (.[$k][]|.e) ;

现在解决方案可以写成两行:

keys_unsorted[] as $k
| $k + (.[$k]|combine)

使用 -r 命令行选项将导致在不带引号的情况下发出字符串。

另一种策略

以下不仅更加通用,而且还说明了一种不同的策略,可以进一步推广和变体:

paths as $p
| getpath($p) as $v
| select($v | type == "string")
| $p
| map(select(type=="string"))
| map(select(. != "e"))
| . + [$v]
| join("")

推荐阅读