jaxDid
jaxDid

Reputation: 23

How do I derive dynamic keys from a nested JSON object with jq?

I'm using jq to transform a JSON input with some nested dynamic keys in this format:

{
  "somePackage": {
    "someVersion": {
      "size": {
        "regular": 1234,
        "compressed": 123
      }
    }
  },
  "someOtherPackage": {
    "someOtherVersion": {
      "size": {
        "regular": 5678,
        "compressed": 567
      }
    }
  }
}

... into an array of objects in this format:

[
  {
    "name": "somePackage",
    "version": "someVersion",
    "regular": 1234,
    "compressed": 123
  },
  {
    "name": "someOtherPackage",
    "version": "someOtherVersion",
    "regular": 5678,
    "compressed": 567
  }
]

I've managed to do it using:

jq 'to_entries | map_values({
  name: .key,
  version: .value|keys[0],
  regular: .value[.value|keys[0]].size.regular,
  compressed: .value[.value|keys[0]].size.compressed
})' input.json

Is there a way to access the dynamic keys of each level in the original JSON so I can use them as values in my output with less repetition?

Upvotes: 2

Views: 356

Answers (1)

peak
peak

Reputation: 116730

You could use jq's so-called "$-variables", e.g.

to_entries
| map_values(
    (.value|keys[0]) as $innerkey
    | { name: .key,
        version: $innerkey,
        regular: .value[$innerkey].size.regular,
        compressed: .value[$innerkey].size.compressed
})

You could also introduce a variable for .value[$innerkey].size, or better yet, simplify:

to_entries
| map_values(
    (.value|keys[0]) as $innerkey
    | { name: .key, version: $innerkey }
      + .value[$innerkey].size )

Please note that keys sorts the keys, so although it does not much matter in this case, using keys_unsorted is a possibility worth bearing in mind.

Upvotes: 2

Related Questions