Skip to content

Instantly share code, notes, and snippets.

@IAmStoxe
Last active March 7, 2024 14:00
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save IAmStoxe/a36b6f043819fad1821e7cfd7e903a5b to your computer and use it in GitHub Desktop.
Save IAmStoxe/a36b6f043819fad1821e7cfd7e903a5b to your computer and use it in GitHub Desktop.
This example shows you how to utilize jq to loop bash script through an array of JSON values.
jsonData='[{"name": "name#1","value": "value#1"},{"name": "name#2","value": "value#2"}]'
for row in $(echo "${jsonData}" | jq -r '.[] | @base64'); do
_jq() {
echo "${row}" | base64 --decode | jq -r "${1}"
}
# OPTIONAL
# Set each property of the row to a variable
name=$(_jq '.name')
value=$(_jq '.value')
# Utilize your variables
echo "$name = $value"
done
# $ stoxe@box:~$ ./loop-json-test.sh
# name#1 = value#1\
# name#2 = value#2
@nate
Copy link

nate commented Jun 29, 2020

😍 omg look at all those beautiful quotes 😍

@sjackson0109
Copy link

sjackson0109 commented Jul 11, 2021

I did this without using base64.

The trick is to treat the data as column data sets, and then with a simple for loop, you are looping over the whitespace.

for row in $(jq -c '.data | map(.) | .[]' myjsonfile.json); do
    _jq() {
     echo ${row} | jq -r "${1}"
    }
   echo $(_jq '.desc') "=" $(_jq '.name')
done

And another type of loop:

jq -c '.data | map(.) | .[]' myjsonfile.json | while read siteJSON;
do
    name=$(echo $siteJSON | jq -r .name)
    desc=$(echo $siteJSON | jq -r .desc)
    echo $desc "=" $name
    # do your processing here
done```

@lhenze
Copy link

lhenze commented Nov 10, 2021

Thank you for sharing this! I wasn't sure how to pipe to a filter after invoking the _jq method,
so I used a variation --

for row in $(echo "${jsonData}" | jq -r '.daos[] | @base64'); do
     name=$(echo ${row} | base64 --decode | jq -r '.name | @html' )
done

Which seems to work for that use case.

@yertto
Copy link

yertto commented Aug 29, 2022

How bout just:

echo '[{"name": "name #1", "value": "value #1"} , {"name": "name#2", "value": "value#2"}]' |

   jq --raw-output 'map("\(.name) = \(.value)")[]'
name #1 = value #1
name#2 = value#2

Or if you really did want to drop down into the bash loop...
Could you avoid messing with base64 and multiple calls to jq and just use tabs to separate the values?

ie. where:

  • jq outputs lines of tab separated values using @tsv
  • then bash reads those lines into variables using $\t as the IFS (Input Field Separator)
echo '[{"name": "name #1", "value": "value #1"} , {"name": "name#2", "value": "value#2"}]' |

jq --raw-output 'map([.name, .value])[] | @tsv' |

while IFS=$'\t' read name value; do
    echo "$name = $value"
done
name #1 = value #1
name#2 = value#2

(NB. the sprinklings of whitespace in the input JSON for an extra degree of difficulty.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment