get the first (or n'th) element in a jq json parsing
JsonJqJson Problem Overview
I can get the 1st element in a json inside []
$ echo '[{"a":"x", "b":true}, {"a":"XML", "b":false}]' | jq '.[1]'
{
"a": "XML",
"b": false
}
But if the json is already disassembled (for instance, after filtering entries using 'select'), how can I choose a single entry and avoid the error seen here?
$ echo '[{"a":"x", "b":true}, {"a":"x", "b":false},{"a":"XML", "b":false}]' | jq '.[] | select( .a == "x")'
{
"a": "x",
"b": true
}
{
"a": "x",
"b": false
}
$ echo '[{"a":"x", "b":true}, {"a":"x", "b":false},{"a":"XML", "b":false}]' | jq '.[] | select( .a == "x") | .[1]'
jq: error (at <stdin>:1): Cannot index object with number
Json Solutions
Solution 1 - Json
You can wrap the results from select
in an array:
jq '[.[]|select(.a=="x")][0]' your.json
Output:
{
"a": "x",
"b": false
}
Solution 2 - Json
jq also provides first/0
, last/0
, nth/1
so in this case the filter
( map(select(.a == "x")) | first )
, ( map(select(.a == "x")) | last )
, ( map(select(.a == "x")) | nth(1) )
produces
{
"a": "x",
"b": true
}
{
"a": "x",
"b": false
}
{
"a": "x",
"b": false
}
Additional streaming forms 'first/1', 'last/1' and 'nth/2' are also available so with this data
( first(.[] | select(.a == "x")) )
, ( last(.[] | select(.a == "x")) )
, ( nth(1; .[] | select(.a == "x")) )
produces
{
"a": "x",
"b": true
}
{
"a": "x",
"b": false
}
{
"a": "x",
"b": false
}
Solution 3 - Json
Many of the previous answers work by avoiding to create a stream of objects in the first place. But what if you are starting with a stream of objects—for example JSON-formatted application logs? If your input file (or stream) has multiple objects in it, all you need to do to choose a single entry from a stream of independent objects is to use the --slurp
option (or -s
for the short form):
> o --slurp/-s: > > Instead of running the filter for each JSON object in the input, read > the entire input stream into a large array and run the filter just once.
Then you can just index into the array. For example, to get second item (with index 1):
jq --slurp '.[1]'
Putting this together with your original question, where you want to select that item from a stream:
echo '{"a":"x", "b":true} {"a":"XML", "b":false}' | jq --slurp '.[1]'
which results in this output:
{
"a": "XML",
"b": false
}
Solution 4 - Json
use map
cat raw.json|jq -r -c 'map(select(.a=="x"))|.[1]'
map
recivce a filter to filter an array.
this command
cat raw.json|jq -r -c 'map(select(.a=="x"))'
give the middle result
[{"a":"x","b":true},{"a":"x","b":false}]
.[1]
take the first element