Ask Bjørn Hansen
Ask Bjørn Hansen

Reputation: 6943

jq: sort object values

I want to sort this data structure by the object keys (easy with -S and sort the object values (the arrays) by the 'foo' property.

I can sort them with

jq -S '
  . as $in
  | keys[]
  | . as $k
  | $in[$k] | sort_by(.foo)
    ' < test.json

... but that loses the keys.

I've tried variations of adding | { "\($k)": . }, but then I end up with a list of objects instead of one object. I also tried variations of adding to $in (same problem) or using $in = $in * { ... }, but that gives me syntax errors.

The one solution I did find was to just have the separate objects and then pipe it into jq -s add, but ... I really wanted it to work the other way. :-)

Test data below:

{
    "": [
        { "foo": "d" },
        { "foo": "g" },
        { "foo": "f" }
    ],
    "c": [
        { "foo": "abc" },
        { "foo": "def" }
    ],
    "e": [
        { "foo": "xyz" },
        { "foo": "def" }
    ],
    "ab": [
        { "foo": "def" },
        { "foo": "abc" }
    ]
}

Upvotes: 1

Views: 2293

Answers (3)

peak
peak

Reputation: 116740

If for some reason using the -S command-line option is not a satisfactory option, you can also perform the by-key sort using the to_entries | sort_by(.key) | from_entries idiom. So a complete solution to the problem would be:

.[] |= sort_by(.foo)
| to_entries | sort_by(.key) | from_entries

Upvotes: 0

Ask Bj&#248;rn Hansen
Ask Bj&#248;rn Hansen

Reputation: 6943

@user197693 had a great answer. A suggestion I got in a private message elsewhere was to use

jq -S 'with_entries(.value |= sort_by(.foo))'

Upvotes: 0

user197693
user197693

Reputation: 2045

Maybe this?

jq -S '.[] |= sort_by(.foo)'

Output

{
  "": [
    {
      "foo": "d"
    },
    {
      "foo": "f"
    },
    {
      "foo": "g"
    }
  ],
  "ab": [
    {
      "foo": "abc"
    },
    {
      "foo": "def"
    }
  ],
  "c": [
    {
      "foo": "abc"
    },
    {
      "foo": "def"
    }
  ],
  "e": [
    {
      "foo": "def"
    },
    {
      "foo": "xyz"
    }
  ]
}

Upvotes: 2

Related Questions