jq is useful utility, but I use it infrequently and each time I have to check what was the filters syntax. This cheat sheet helps we to recall what is the expression that I need. Hopefully it would help others too. For full guide refer to the official jq manual.
Given the following JSON:
{
"menus": {
"File": {
"enabled": true,
"menu_items": [
{ "label": "New", "enabled": true },
{ "label": "Open...", "enabled": true },
{ "label": "Print...", "enabled": false },
{ "label": "Exit", "enabled": true }
]
},
"Edit": {
"enabled": false,
"menu_items": [
{ "label": "Copy", "enabled": false },
{ "label": "Cut", "enabled": false },
{ "label": "Paste", "enabled": true }
]
}
}
}
The following script will select the labels of all enabled menu items which are nested within enabled menus:
jq --raw-output '.menus[] | select ( .enabled == true ) | .menu_items[] | select ( .enabled == true ) | .label'
The output is:
New
Open...
Exit
To navigate within object use dot (.
). Single dot (.
) means the object root.
echo '{ "foo": { "bar": 5 } }' | jq '.foo.bar'
# Output: 5
To access a single value in an array use square brackets ([]
).
echo '[1,2,3]' | jq '.[0]'
# Output: 1
To get all elements of an array use square brackets without index:
echo '[1,2,3]' | jq '.[]'
# Output: 1 2 3
You can use the same syntax to get all values of object, ignoring the keys.
echo '{"foo": 3, "bar": 5 }' | jq '.[]'
# Output: 3 5
Use pipe (|
) to chain multiple filters.
echo '{ "foo": { "bar": 5 } }' | jq '.foo | .bar'
# Output: 5
To select (filter) only elements that satisfy given condition use select
.
echo '[1,2,3,4,5]' | jq '.[] | select( . > 2) | select( . < 5)'
# Output: 3 4
echo '[ { "value": 1 }, { "value": 2 } ]' | jq '.[] | select( .value > 1)'
# Output: { "value": 2 }
By default jq returns JSON values. This means that if you select string value you will get quotes around it:
echo '{ "foo": "bar" }' | jq '.foo'
# Output: "bar"
If you want to use the values in Bash script it might be more convenient to get the raw values (without the quotes). Just use the --raw-output
option:
echo '{ "foo": "bar" }' | jq --raw-output '.foo'
# Output: bar
Your data is in YAML format? No problems. Use yq instead. It will convert you YAML to JSON and then send it to jq.