echo "$REPOS" | jq '.[].repositoryName' | while read -r repo; do echo "do something with $repo"; done
Output:
do something with "repo_a" do something with "repo_b" do something with "repo_c" do something with "repo_d"
Or without quotes:
echo "$REPOS" | jq -r '.[].repositoryName' | while read -r repo; do echo "do something with $repo"; done
Output:
do something with repo_a do something with repo_b do something with repo_c do something with repo_dAnswer from Cyrus on Stack Overflow
echo "$REPOS" | jq '.[].repositoryName' | while read -r repo; do echo "do something with $repo"; done
Output:
do something with "repo_a" do something with "repo_b" do something with "repo_c" do something with "repo_d"
Or without quotes:
echo "$REPOS" | jq -r '.[].repositoryName' | while read -r repo; do echo "do something with $repo"; done
Output:
do something with repo_a do something with repo_b do something with repo_c do something with repo_d
If you want to iterate over JSON values instead of a single field value, you can use the -c option so you end up with one JSON element per line:
repositories='{
"repositories": [
{
"repositoryName": "repo_a",
"repositoryId": "XXXXXX"
},
{
"repositoryName": "repo_b",
"repositoryId": "XXXXXX"
},
{
"repositoryName": "repo_c",
"repositoryId": "XXXXXX"
},
{
"repositoryName": "repo_d",
"repositoryId": "XXXXXX"
}
]
}'
while read repository
do
name=$(echo "$repository" | jq -r .repositoryName)
id=$(echo "$repository" | jq -r .repositoryId)
echo "
{name}"
done < <(echo "$repositories" | jq -c '.repositories[]')
JSON with jq into bash array / loop through - Unix & Linux Stack Exchange
iteration - Output specific key value in object for each element in array with jq for JSON - Stack Overflow
Using jq to loop through file of JSON objects
How to loop through an array of objects?
It's generally a good idea to avoid looping over the result of a command substitution. It's inelegant as the command in the substitution must finish executing before the loop can even start running, it's inefficient as the full result of the command in the substitution must be stored in memory, and it's prone to errors since the shell must be allowed to split the output of the command on whitespace and subject the resulting words to filename globbing.
It's better to use read in a while loop:
#!/bin/sh
curl -s 'localhost:14002/api/sno' |
jq -r '.satellites[].id' |
while IFS= read -r id; do
curl -s 'localhost:14002/api/sno/satellite/'"$id"
done |
jq -r \
--argjson auditScore 1 \
--argjson suspensionScore 1 \
--argjson onlineScore 0.9 \
'.audits as
a.satelliteName as $name |
reduce ($ARGS.named|keys[]) as
a[
ARGS.named[$key] then (
. + ["\($key) below threshold: \(
key]) for \($name)"]
) else . end
) | .[]'
This script assumes that you can contact your REST endpoints on localhost:14002 (the Docker container might be made to expose that port, for example). If you need to use the docker exec command to access the API, then replace the plain calls to curl with, e.g.
docker exec -i curl -s 'localhost:14002/api/sno'
For the updated question, using the api/sno/satellites endpoint:
#!/bin/sh
curl -s 'localhost:14002/api/sno/satellites' |
jq -r \
--argjson auditScore 1 \
--argjson suspensionScore 1 \
--argjson onlineScore 0.9 \
'.audits[] as
a.satelliteName as $name |
reduce ($ARGS.named|keys[]) as
a[
ARGS.named[$key] then (
. + ["\($key) below threshold: \(
key]) for \($name)"]
) else . end
) | .[]'
Apart from a minor adjustment to the jq expression, this is essentially the same code as above, but bypassing the first curl call to fetch all the IDs, and the loop.
I‘ve found one possible answer on stackoverflow:
for sat in `docker exec -i storagenode wget -qO - localhost:14002/api/sno | jq .satellites[].id -r`
do
docker exec -i storagenode wget -qO - localhost:14002/api/sno/satellite/$sat \
| jq --raw-output \
--argjson auditThreshold 1 \
--argjson suspensionThreshold 1 \
--argjson onlineThreshold 1 \
'.audits
| .satelliteName as $name
| (
[{auditScore}, $auditThreshold],
[{suspensionScore}, $suspensionThreshold],
[{onlineScore}, $onlineThreshold]
)
| select(.[0][] < .[1])
| "\(.[0] | keys[]) (\(.[0][])) below threshold (\(.[1])) for \($name)"
'
done
The command-line tool jq writes to STDOUT and/or STDERR. If you want to write the .AssetId information to STDOUT, then one possibility would be as follows:
jq -r ".[] | .AssetId" input.json
Output:
14462955
114385498
29715011
98253651
A more robust incantation would be: .[] | .AssetId? but your choice will depend on what you want if there is no key named "AssetId".
You can also do it via this command.
jq ".[].AssetId" input.json
if array like be that which is in my case
{
"resultCode":0,
"resultMsg":"SUCCESS",
"uniqueRefNo":"111222333",
"list":[
{
"cardType":"CREDIT CARD",
"isBusinessCard":"N",
"memberName":"Bank A",
"memberNo":10,
"prefixNo":404591
},
{
"cardType":"DEBIT CARD",
"isBusinessCard":"N",
"memberName":"Bank A",
"memberNo":10,
"prefixNo":407814
},
{
"cardType":"CREDIT CARD",
"isBusinessCard":"N",
"memberName":"Bank A",
"memberNo":10,
"prefixNo":413226
}
]
}
you can get the prefixNo with below jq command.
jq ".list[].prefixNo" input.json
For more specific case on array iterating on jq you can check this blogpost
I know how to loop through an array of JSON objects and access values, but the data I have is not formatted as an array. It is simply a file full of JSON objects, separated by line. Is it still possible to parse this data with jq without formatting the file as a giant array?
Right now I'm essentially using a command like this:
cat file.json | jq '.[] | .name'
[
{
"key": "key value blah blah 1",
"secret": "secret value blah blah 1"
}, {
"key": "key value blah blah 2",
"secret": "secret value blah blah 2"
}, {
"key": "key value blah blah 3",
"secret": "secret value blah blah 3"
}, {
"key": "key value blah blah 4",
"secret": "secret value blah blah 4"
},
]
I need to match a given key with the keys in the array and assign the secret to a variable
something like:
for key in array; do
if key = "my key value to be matched"; then
$secretvalue = $secretfromtheobject
fi
done
echo $secretvalueThis is just how I want it to be I know the code above is incomplete and wrong.
You are trying to invoke myfile.js as a command. You need this:
output=$(cat myfile.js)
instead of this:
output=$(myfile.js)
But even then, your current approach isn't going to work well if the data has whitespace in it (which it does, based on the sample you posted). I suggest the following alternative:
jq -c '.[]' < myfile.js |
while read -r row
do
echo "$row"
done
Output:
{"id":1,"name":"blah blah"}
{"id":2,"name":"xxx"}
Edit:
If your data is arising from a previous process invocation, such as mongo in your case, you can pipe it directly to jq (to remain portable), like this:
mongo myfile.js |
jq -c '.[]' |
while read -r row
do
echo "$row"
done
How can I make jq -c '.[]' < (mongo myfile.js) work?
In a bash shell, you would write an expression along the following lines:
while read -r line ; do .... done < <(mongo myfile.js | jq -c .[])
Note that there are two occurrences of "<" in the above expression.
Also, the above assumes mongo is emitting valid JSON. If it emits //-style comments, those would have somehow to be removed.
Comparison with piping into while
If you use the idiom:
... | while read -r line ; do .... done
then the bindings of any variables in .... will be lost.