使用jq将字符串拆分为嵌套对象

时间:2016-03-22 05:28:48

标签: json jq

我试图将consul kv中的数据导入json,并为领事中的每个深度级别设置一个嵌套对象。

示例json从领事返回:

[
  {
    "LockIndex": 0,
    "Key": "foobar/testing",
    "Flags": 0,
    "Value": "xxxxx",
    "CreateIndex": 833,
    "ModifyIndex": 833
  },
  {
    "LockIndex": 0,
    "Key": "foobar/bazbar",
    "Flags": 0,
    "Value": "xxxxx",
    "CreateIndex": 833,
    "ModifyIndex": 833
  }
]

所需的JSON:

[
  {
    "foobar": {
      "testing": "xxxxx",
      "bazbar": "xxxxx"
    }
  }
]

我与jq '.[] | objects | {Key: .Key | split("/"), Value: .Value}'关系密切,但我根本不了解如何根据.Key的split()和创建嵌套对象进行递归。我认为我还需要sort_by(.Key)来处理乱序数据,除非我可以| add任意地让jq解析结构。

我意识到xxxxx是base64编码的,希望base64d很快会合并,但在那之前,我想我可以通过shell后处理解决这个问题。

3 个答案:

答案 0 :(得分:7)

以下内容在您给出的特定情况下生成感兴趣的JSON对象,但在有多个" foobar"的情况下也会提供合理的概括。前缀:

map( . as $o | .Key | split("/") | {(.[0]): {(.[1]): ($o|.Value) }} )
| reduce .[] as $o
    ( {};
      ($o|keys[0]) as $key | . + { ($key): (.[$key] + $o[$key]) } )

输出:

{
  "foobar": {
    "testing": "xxxxx",
    "bazbar": "xxxxx"
  }
}

答案 1 :(得分:1)

以下是使用 reduce 拆分 setpath

的解决方案
[
  reduce (.[] | [(.Key | split("/")), .Value]) as [$p,$v] (
    {}
  ; setpath($p; $v)
  )
]

答案 2 :(得分:0)

这个简单的解决方案使用setpath处理任何深度,非常适合解析Consul KV响应:

    reduce .[] as $item ({}; setpath($item.Key | split("/"); $item.Value))