Using jq to split a string into nested objects

Viewed 9847

I'm trying to export data from consul kv into json with a nested object for each level of depth in consul.

Example json returned from consul:

[
  {
    "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
  }
]

Desired JSON:

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

I'm sort of close with jq '.[] | objects | {Key: .Key | split("/"), Value: .Value}' but I'm just not understanding how I can recurse based on a split() of .Key and create nested objects. I think I'll also need to sort_by(.Key) to handle out of order data, unless I can | add arbitrarily and have jq resolve the structure.

I realize xxxxx is base64 encoded, and hopefully, base64d will get merged soon but until then I think I can handle decoding this with shell post-processing.

3 Answers

This simple solution uses setpath to handle any depth and works great for parsing Consul KV responses:

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