Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jq group by property in array

Tags:

json

bash

shell

jq

I have an input json document as so:

[
  {
    "Name": "one",
    "Tags": [
      {
        "Key": "Name",
        "Value": "important"
      },
      {
        "Key": "OtherTag",
        "Value": "irrelevant"
      }
    ]
  },
  {
    "Name": "two",
    "Tags": [
      {
        "Key": "OtherTag",
        "Value": "irrelevant2"
      },
      {
        "Key": "Name",
        "Value": "important"
      }
    ]
  },
  {
    "Name": "three",
    "Tags": [
      {
        "Key": "Name",
        "Value": "important2"
      },
      {
        "Key": "OtherTag",
        "Value": "irrelevant3"
      }
    ]
  }
]

I want to use jq to group the three records by tag Value where the Key = "Name". The result would be two arrays, one with two records in it and one with one. The array with two records would have two because both records share the same tag with a value of "important". Here is what the result would look like:

[
  [
    {
      "Name": "one",
      "Tags": [
        {
          "Key": "Name",
          "Value": "important"
        },
        {
          "Key": "OtherTag",
          "Value": "irrelevant"
        }
      ]
    },
    {
      "Name": "two",
      "Tags": [
        {
          "Key": "OtherTag",
          "Value": "irrelevant2"
        },
        {
          "Key": "Name",
          "Value": "important"
        }
      ]
    },
  ],
  [
    {
      "Name": "three",
      "Tags": [
        {
          "Key": "Name",
          "Value": "important2"
        },
        {
          "Key": "OtherTag",
          "Value": "irrelevant3"
        }
      ]
    }
  ]
]

I just can't figure out how to do this with jq. Does anyone have any ideas?

like image 355
Martian Tycoon Avatar asked Apr 15 '26 00:04

Martian Tycoon


1 Answers

Your proposed solution is fine, but if you don't mind converting the arrays of Key-Value pairs into objects, then the following can be used:

map( .Tags |= from_entries ) | group_by(.Tags.Name) 

This at least makes the "group_by" easy to understand; furthermore, it would be easy to convert the .Tags objects back to key-value pairs (with lower-case "key" and "value"):

map( .Tags |= from_entries ) | group_by(.Tags.Name)
| map(map( .Tags |= to_entries))

Key/Value capitalization

One way to recover the capitalized Key/Value tags would be to tweak the above as follows:

def KV: map( {Key: .key, Value: .value} );

map( .Tags |= from_entries ) | group_by(.Tags.Name)
| map(map( .Tags |= (to_entries | KV)))
like image 188
peak Avatar answered Apr 16 '26 15:04

peak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!