failed to extract data from json with jq command - json

I've this json.
I want to extract test fields which their values equal to true.
I tried with jq and got that error, pls any fix ?
$- jq '.[].name | select(.[].test == "true")' ddd
jq: error (at ddd:12): Cannot iterate over string ("AA")
[
{
"name": "AA",
"program_url": "https://www.google.com",
"test": false
},
{
"name": "BB",
"program_url": "https://yahoo.com",
"test": true
}
]

Are you looking for this? It iterates over the array .[], selects those item objects whose .test field evaluates to true (implicit), and traverses further down to the .name field. Using the --raw-output (or -r) option renders the output raw text (instead of JSON string in this case).
jq -r '.[] | select(.test).name' ddd
BB
Demo

Related

Select only non-empty objects from array

I have a JSON array with objects as items. Some of the objects have properties, some don't. How can I filter the list with jq to keep only non-empty objects in the list?
Input:
[
{},
{ "x": 42 },
{},
{ "y": 21 },
{},
{ "z": 13 }
]
Expected output:
[
{ "x": 42 },
{ "y": 21 },
{ "z": 13 }
]
I tried jq 'select(. != {})', but the result still contains all items. Using jq 'map(select(empty))' doesn't keep any item and returns an empty array!
You need map to make select test individual objects:
jq 'map(select(. != {}))'
map is required to apply the filter to every item in the array. Then any can be used: it will return true for objects with at least one property, and false if the object is empty.
$ jq -n '{} | any'
false
$ jq -n '{x:42} | any'
true
empty is not a test, but a generator for "no value" (docs).
Solution:
map(select(any))
As noted by user Philippe in the comments, using any only works if the values of the objects' properties are not false. It would detect objects such as {"x":false} as "empty". A better approach is comparing the empty object directly or using length:
map(select(length>0))
Just use the del filter:
jq 'del(.[] | select(length == 0))'
or
jq 'del(.[] | select(. == {}))'

How to output the value of a json file in one line using jq, including one space for each value?

{
"entries": [
{
"Name": "cat",
"size": "100"
},
{
"Name": "dog",
"size": "200"
}
]
}
I have a json file like the one above, and I want to output the value of Name in one line including spaces.
With the following command I used, the output was output with consecutive values without spaces as follows.
jq -j .entries[].Name test.json
output
catdog
but I want to output the value as follows using the Name key.
cat dog
How can I output a single line including single spaces for each value in a json file?
Just join them?
jq -r '.entries | map(.Name) | join(" ")' test.json

Why is JQ treating arrays as a single field in CSV output?

With the following input file:
{
"events": [
{
"mydata": {
"id": "123456",
"account": "21234"
}
},
{
"mydata": {
"id": "123457",
"account": "21234"
}
}
]
}
When I run it through this JQ filter,
jq ".events[] | [.mydata.id, .mydata.account]" events.json
I get a set of arrays:
[
"123456",
"21234"
]
[
"123457",
"21234"
]
When I put this output through the #csv filter to create CSV output:
jq ".events[] | [.mydata.id, .mydata.account] | #csv" events.json
I get a CSV file with one record per row:
"\"123456\",\"21234\""
"\"123457\",\"21234\""
I would like CSV file with two records per row, like this:
"123456","21234"
"123457","21234"
What am I doing wrong?
Use the -r flag.
Here is the explanation in the manual:
--raw-output / -r: With this option, if the filter's result is a string then it will be written directly to standard output rather than
being formatted as a JSON string with quotes.
jq -r '.events[] | [.mydata.id, .mydata.account] | #csv'
Yields
"123456","21234"
"123457","21234"

jq to output results as JSON

jq is suppose to
process/filter JSON inputs and producing the filter's results as JSON
However, I found that after the jq process/filter, output result is no longer in JSON format any more.
E.g., https://stedolan.github.io/jq/tutorial/#result5, i.e.,
$ curl -s 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.[] | {message: .commit.message, name: .commit.committer.name}'
{
"message": "Merge pull request #162 from stedolan/utf8-fixes\n\nUtf8 fixes. Closes #161",
"name": "Stephen Dolan"
}
{
"message": "Reject all overlong UTF8 sequences.",
"name": "Stephen Dolan"
}
. . .
Is there any workaround?
UPDATE:
How to wrap the whole return into a json structure of:
{ "Commits": [ {...}, {...}, {...} ] }
I've tried:
jq '.[] | Commits: [{message: .commit.message, name: .commit.committer.name}]'
jq 'Commits: [.[] | {message: .commit.message, name: .commit.committer.name}]'
but neither works.
Found it, on the same page,
https://stedolan.github.io/jq/tutorial/#result6
If you want to get the output as a single array, you can tell jq to “collect” all of the answers by wrapping the filter in square brackets:
jq '[.[] | {message: .commit.message, name: .commit.committer.name}]'
Technically speaking, unless otherwise instructed (notably with the -r command-line option), jq produces a stream of JSON entities.
One way to convert an input stream of JSON entities into a JSON array containing them is to use the -s command-line option.
Response to UPDATE
To produce a JSON object of the form:
{ "Commits": [ {...}, {...}, {...} ] }
you could write something like:
jq '{Commits: [.[] | {message: .commit.message, name: .commit.committer.name}]}'
(jq understands the '{Commits: _}' shorthand.)

jq: How to match one of array and get sibling value

I have some JSON like this:
{
"x": [
{
"name": "Hello",
"id": "211"
},
{
"name": "Goodbye",
"id": "221"
},
{
"name": "Christmas",
"id": "171"
}
],
"y": "value"
}
Using jq, given a name value (e.g. Christmas) how can I get it's associated id (i.e. 171).
I've got as far as being able to check for presence of the name in one of the array's objects, but I can't work out how to filter it down
jq -r 'select(.x[].name == "Christmas")'
jq approach:
jq -r '.x[] | select(.name == "Christmas").id' file
171
The function select(boolean_expression) produces its input unchanged if boolean_expression returns true for that input, and produces no output otherwise.
It can also been done like:
jq '.x[] | select(.name == "Christmas").id'
Also you can try this at link online jq play