Some jq examples. All quotes are from the jq manual.

A sample json file is as below.

$ cat sample.json
{
    "apple-weight": [
        60
    ],
    "orange-weight": [
        50
    ],
    "banana-weight": [
        20,
        35
    ]
}

The keys builtin function

$ jq '. | keys' sample.json
[
  "apple-weight",
  "banana-weight",
  "orange-weight"
]

The builtin function keys, when given an object, returns its keys in an array.

Array/Object Value Iterator: .[]

$ jq '. | keys[]' sample.json
"apple-weight"
"banana-weight"
"orange-weight"

If you use the .[index] syntax, but omit the index entirely, it will return all of the elements of an array.

Running .[] with the input [1,2,3] will produce the numbers as three separate results, rather than as a single array.

You can also use this on an object, and it will return all the values of the object.

exp as $x | ... and String Interpolation

$ jq '. | keys[] as $k | "\($k), \(.[$k])"' sample.json
"apple-weight, [60]"
"banana-weight, [20,35]"
"orange-weight, [50]"

The expression exp as $x | ... means: for each value of expression exp, run the rest of the pipeline with the entire original input, and with $x set to that value. Thus as functions as something of a foreach loop.

The '. | keys[] as $k | "\($k), \(.[$k])"' means for each value of . | keys[], which are “apple-weight”, “banana-weight” and “orange-weight”, run the rest of pipeline, i.e. "\($k), \(.[$k])", which is string interpolation.

String interpolation - (foo)

More Complex Expression in String interpolation

$ jq '. | keys[] as $k | "\($k), \(.[$k][0])"  ' sample.json
"apple-weight, 60"
"banana-weight, 20"
"orange-weight, 50"

\(.[$k][0]) is replaced with the value of .["apple-weight"][0].

Array construction: []

$ jq -c '. | keys[] as $k | [$k, .[$k][0]] ' sample.json
["apple-weight",60]
["banana-weight",20]
["orange-weight",50]
$ jq  '[ . | keys[] as $k | [$k, .[$k][0]] ] ' sample.json
[
  [
    "apple-weight",
    60
  ],
  [
    "banana-weight",
    20
  ],
  [
    "orange-weight",
    50
  ]
]

If you have a filter X that produces four results, then the expression [X] will produce a single result, an array of four elements.

The . | keys[] as $k | [$k, .[$k][0]] produces three results, enclosing it with [] produces an array of these three elements.

Object Construction: {}

$ jq  ' . | keys[] as $k | {category: $k, weight: .[$k][0]}  ' sample.json
{
  "category": "apple-weight",
  "weight": 60
}
{
  "category": "banana-weight",
  "weight": 20
}
{
  "category": "orange-weight",
  "weight": 50
}

Object Construction: {} and Array construction: []

$ jq  '[ . | keys[] as $k | {category: $k, weight: .[$k][0]} ] ' sample.json
[
  {
    "category": "apple-weight",
    "weight": 60
  },
  {
    "category": "banana-weight",
    "weight": 20
  },
  {
    "category": "orange-weight",
    "weight": 50
  }
]

The sort function

$ jq  '[ . | keys[] as $k | [$k, .[$k][0]] ] | sort ' sample.json
[
  [
    "apple-weight",
    60
  ],
  [
    "banana-weight",
    20
  ],
  [
    "orange-weight",
    50
  ]
]

The sort functions sorts its input, which must be an array.

Values are sorted in the following order: null, false, true, …

The [ . | keys[] as $k | [$k, .[$k][0]] ] is an array of three elements, each of which itself is an array. These three elements, according to the manual, are sorted “in lexical order”.

The sort_by function

$ jq  '[ . | keys[] as $k | {category: $k, weight: .[$k][0]} ] | sort_by(.weight) ' sample.json
[
  {
    "category": "banana-weight",
    "weight": 20
  },
  {
    "category": "orange-weight",
    "weight": 50
  },
  {
    "category": "apple-weight",
    "weight": 60
  }
]

sort_by(foo) compares two elements by comparing the result of foo on each element.

The [ . | keys[] as $k | {category: $k, weight: .[$k][0]} ] is an array of three objects. The | sort_by(.weight) sorts these three objects by comparing their weight property. The final result is still an array, but sorted.

Select/Filter

$ jq  '[ . | keys[] as $k | {category: $k, weight: .[$k][0]} ] | sort_by(.weight) | .[] | select(.weight >= 50) ' sample.json
{
  "category": "orange-weight",
  "weight": 50
}
{
  "category": "apple-weight",
  "weight": 60
}

The function select(foo) produces its input unchanged if foo returns true for that input, and produces no output otherwise.

The [ . | keys[] as $k | {category: $k, weight: .[$k][0]} ] | sort_by(.weight) produces a sorted array. The following .[], i.e. array iterator, feeds select(.weight >= 50) with three elements of that array. The final result is elements whose weight is equal or larger than 50.

The command below, using map, produces the same result.

$ jq  '[ . | keys[] as $k | {category: $k, weight: .[$k][0]} ] | sort_by(.weight) | map(select(.weight >= 50)) ' sample.json
[
  {
    "category": "orange-weight",
    "weight": 50
  },
  {
    "category": "apple-weight",
    "weight": 60
  }
]

Multiple Conditions in select

$ jq  '[ . | keys[] as $k | {category: $k, weight: .[$k][0]} ] | sort_by(.weight) | .[] | select( (.weight >= 50) and (.weight < 60))  ' sample.json
{
  "category": "orange-weight",
  "weight": 50
}