使用jq获取所有嵌套的键和值

问题描述 投票:0回答:3

我有一个这样的json

{
  "outer1": {
    "outer2": {
      "outer3": {
        "key1": "value1",
        "key2": "value2"
      }
    },
    "outer4": {
      "key1": "value1",
      "key2": "value2"
    }
  }
}

我希望输出是

[outer1.outer2.outer3]
key1 = value1
key2 = value2

[outer1.outer2.outer4]
key1 = value1
key2 = value2

我尝试了

jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' test.json
但这不是我想要的

json bash jq key-value
3个回答
6
投票

假设您的输入如下所示:

{
  "outer1": {
    "outer2": {
      "outer3": {
        "key1": "value1",
        "key2": "value2"
      },
      "outer4": {
        "key1": "value1",
        "key2": "value2"
      }
    }
  }
}

您可以使用

--stream
选项将输入读取为路径值对流。例如:

jq --stream -n '
  reduce (inputs | select(has(1))) as [$path, $val] ({};
    .[$path[:-1] | join(".")][$path[-1]] = $val
  )
'
{
  "outer1.outer2.outer3": {
    "key1": "value1",
    "key2": "value2"
  },
  "outer1.outer2.outer4": {
    "key1": "value1",
    "key2": "value2"
  }
}

接下来,根据您的需要格式化此 JSON。例如,对两个级别都使用

to_entries

jq --stream -nr '
  reduce (inputs | select(has(1))) as [$path, $val] ({};
    .[$path[:-1] | join(".")][$path[-1]] = $val
  )
  | to_entries[] | "[\(.key)]", (
      .value | to_entries[] | "\(.key) = \(.value)"
    ), ""
'
[outer1.outer2.outer3]
key1 = value1
key2 = value2

[outer1.outer2.outer4]
key1 = value1
key2 = value2


或者,将这两个步骤组合成一个

foreach
迭代,并使用滑动上下文窗口作为状态:

jq --stream -nr '
  foreach (inputs | select(has(1))) as [$path, $val] ([];
    [last, ($path[:-1] | join("."))];
    (select(first != last) | "\n[\(last)]"), "\($path[-1]) = \($val)"
  )                                                              
'

2
投票

我的看法是这样的:

. as $data
| [ path(.. | scalars) ]
| map( . as $p | { prefix: $p[0:-1]|join("."), key: $p[-1], value: $data | getpath($p) })
| group_by(.prefix)[]
| "[\(first.prefix)]", (.[] | "\(.key)=\(.value)")

基本上:

  • 找到所有标量,
  • 获取这些标量的路径(如
    ["outer1","outer2","outer3","key1"]
  • 创建路径的中间表示,分为前缀(如
    outer1.outer2.outer3
    )、键(
    key1
    )和实际值(
    value1
  • 使用前缀对它们进行分组
  • 格式

0
投票

如果您尝试生成 TOML 编码文档,还可以考虑使用 kislyuk/yq,它是一个用于处理(YAML、XML 和)TOML 文档的

jq
包装器。 TOML 处理器称为
tomlq
,它在 TOML 和 JSON 之间进行转码,以便可以直接应用
jq
过滤器。不过,对于您的用例,过滤器只需要发出变量的内容,该变量使用 jq 的
--argfile
选项填充 JSON 输入文件的内容(因为从
stdin
读取和直接文件参数预计会是 TOML 编码的,因此使用
-n
)。最终,
-t
选项将(最终)JSON 文档(返回)转换为 TOML。输出与您期望的输出略有不同,但如果您的目标是生成 TOML 文档,您可以受益于
tomlq
自动提供有效且格式良好的结构。

tomlq -n -t '$f' --argfile f file.json
[outer1.outer2]
[outer1.outer2.outer3]
key1 = "value1"
key2 = "value2"

[outer1.outer2.outer4]
key1 = "value1"
key2 = "value2"
© www.soinside.com 2019 - 2024. All rights reserved.