5

Given the following JSON:

{
  "alice": { "items": ["foo", "bar"] },
  "bob": { "items": ["bar", "foo"] },
  "charlie": { "items": ["foo", "bar"] }
}

I can sort the items array as follows:

$ jq < users.json 'map(.items |= sort)'
[
  {
    "items": [
      "bar",
      "foo"
    ]
  },
  {
    "items": [
      "bar",
      "foo"
    ]
  },
  {
    "items": [
      "bar",
      "foo"
    ]
  }
]

However, this crashes if any user doesn't have items:

{
  "alice": { "items": ["foo", "bar"] },
  "bob": { "items": ["bar", "foo"] },
  "charlie": {}
}

Trying to sort it gives an error.

$ jq < users.json 'map(.items |= sort)'
jq: error (at <stdin>:5): null (null) cannot be sorted, as it is not an array

How can I obtain the following?

$ jq < users.json SOMETHING
[
  {
    "items": [
      "bar",
      "foo"
    ]
  },
  {
    "items": [
      "bar",
      "foo"
    ]
  },
  {
    "items": [
    ]
  }
]

I've tried using // [] but I'm not sure how to do this in relation to sorting.

peak
  • 105,803
  • 17
  • 152
  • 177
Wilfred Hughes
  • 29,846
  • 15
  • 139
  • 192

2 Answers2

5

You can preserve the original structure if you map the values of the object using map_values. Then from there, if you want to preserve the absence of the items array, just check for it beforehand.

map_values(if has("items") then .items |= sort else . end)

Otherwise if you don't care about adding the empty items:

map_values(.items |= (. // [] | sort))
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
1

Aha, this seems to work:

$ jq < users.json 'map(.items |= (. // [])) | map(.items |= sort)'
Wilfred Hughes
  • 29,846
  • 15
  • 139
  • 192