用 jq 保留键名展平 JSON

Flatten JSON with jq retaining key names

我正在尝试展平由嵌套对象组成的 JSON。顶层包含几个 key/value 对,其中每个值本身就是一组对象(底层)。

我想使用 jq 得到的只是一个包含底层所有对象的对象数组,每个对象都有一个额外的 key/value 对来标识它最初的顶层密钥属于。

换句话说,我想转一个JSON

{
 "key1": [obj1, obj2],
 "key2": [obj3]
}

转换为普通数组

[OBJ1, OBJ2, OBJ3]

其中每个 OBJi 只是带有额外 key/value 对的原始对象

"parent-key-name": keyx

其中 keyx 将是 obji 所属的顶层密钥,即 "key1" 用于 obj1obj2,以及 "key2" 对于 obj3.

我正在努力解决这样一个事实,即在引用底层中的对象时,例如通过 .[],jq 似乎没有内置功能来访问关联的顶层信息。但是,我是jq的新手,希望毕竟有一个简单的解决方案。

给定以下输入:

{
 "key1": [{"name":"Emma"},{"name":"Bob"}],
 "key2": [{"name":"Jean"}]
}

您可以将项目划分为条目,将键存储在变量中,然后将每个项目的值添加到 value 对象中:

jq  '[ to_entries[] | .key as $parent | .value[] |
   .["parent-key-name"] |= (.+ $parent) ] ' test.json

给出以下输出:

[
  {
    "name": "Emma",
    "parent-key-name": "key1"
  },
  {
    "name": "Bob",
    "parent-key-name": "key1"
  },
  {
    "name": "Jean",
    "parent-key-name": "key2"
  }
]

下面介绍的解决方案包括两个步骤,每个步骤都可能有帮助,例如如果有人想 "flatten" JSON 以稍微不同的方式。

  1. 首先,让我们对obj[i]进行修改"in-place":

    with_entries( .key as $k | .value[] |= ( . + {"parent-key-name": $k} )

示例:

$ jq -n -c -f program.jq

输入: { "key1": [{a:1}, {a:2}], "key2": [{b:3}] }

输出:

{
  "key1": [
    {
      "a": 1,
      "parent-key-name": "key1"
    },
    {
      "a": 2,
      "parent-key-name": "key1"
    }
  ],
  "key2": [
    {
      "b": 3,
      "parent-key-name": "key2"
    }
  ]
}
  1. 要展平,只需将 | [.[]] 附加到上述过滤器即可。这会产生:

    [[{"a":1,"parent-key-name":"key1"},{"a":2,"parent-key-name":"key1"} ],[{"b":3,"parent-key-name":"key2"}]]