'jq - looping through json object and only displaying certain values
I am currently learning how to usage jq. I have a json object and I am able to loop and read values with jq as such cat test.json | jq -r '.test'. However, I am running into some complexity when I only want to display on values that have outdated or deprecated = true but ommit from result if relase = never-update-app or never-upgrade-app. I am trying cat test.json | jq '.test | select(.[].outdated==true)' but this is not returning the desired results. Is this something possible through jq and have it display in the below desired format?
My desired output is shown below:
Release Name Installed Latest Old Deprecated
test-app 1.0.0 2.0.0 true false
json:
{
"test": [{
"release": "myapp1",
"Installed": {
"version": "0.3.0",
"appVersion": "v1.2.6"
},
"Latest": {
"version": "",
"appVersion": ""
},
"outdated": false,
"deprecated": false
}, {
"release": "myapp2",
"Installed": {
"version": "6.5.13",
"appVersion": "1.9.1"
},
"Latest": {
"version": "",
"appVersion": ""
},
"outdated": false,
"deprecated": false
}, {
"release": "test-app",
"Installed": {
"version": "1.0.0",
"appVersion": ""
},
"Latest": {
"version": "2.0.0",
"appVersion": ""
},
"outdated": true,
"deprecated": false
}, {
"release": "never-update-app",
"Installed": {
"version": "1.0.0",
"appVersion": ""
},
"Latest": {
"version": "3.0.0",
"appVersion": ""
},
"outdated": true,
"deprecated": false
}, {
"release": "never-upgrade-app",
"Installed": {
"version": "2.0.0",
"appVersion": ""
},
"Latest": {
"version": "2.0.0",
"appVersion": ""
},
"outdated": false,
"deprecated": true
}]
}
Solution 1:[1]
How to act on each element in an array
You have an array in .test. If you want to extract the individual elements of that array to use in the rest of your filter, use .test[]. If you want to process them but keep the results in an array, use .test|map(...) where ... is the filter you want to apply to the elements of the array.
How to filter objects with multiple conditions
As described in this question you can use the select() filter with multiple conditions. So, for example:
jq '.test[]|
select(
(.outdated or .deprecated) and
.release != "never-update-app" and
.release != "never-upgrade-app"
)'
How to combine non-trivial filters
Use parentheses! As an example, suppose you want to replace the two "never-" tests with a startswith test. By surrounding the pipes with parentheses you isolated the calculation and just get the true/false answer to combine in a boolean expression.
jq '.test[]|
select(
(.outdated or .deprecated) and
(.release|startswith("never-")|not)
)'
How to format results in a table
I think this answer on formatting results in a table is probably sufficient. If you have more specific needs I think you might want to spin this off into a separate question.
Solution 2:[2]
Filter
(["ReleaseName","Installed","Latest","Old","Deprecated"] | @tsv), (.test[] | select( (.outdated==true or .deprecated==true) and ((.release=="never-update-app" or .release=="never-upgrade-app") | not) ) | "\(.release) \(.Installed.version) \(.Latest.version) \(.outdated) \(.deprecated)" / " " | @tsv)
Output
ReleaseName Installed Latest Old Deprecated
test-app 1.0.0 2.0.0 true false
Demo
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Logan Lee |
