user2548436
user2548436

Reputation: 925

Bash Jq parse json string

I've to call a file and pass a json as parameters in this way (suppose that my file is called test.sh), from bash I need to do something like this:

./test.sh "[{\"username\":\"user1\",\"password\":\"pwd1\",\"group\":\"usergroup1\"},{\"username\":\"user2\",\"password\":\"pwd2\",\"group\":\"usergroup2\"},{\"username\":\"user3\",\"password\":\"pwd3\",\"group\":\"usergroup3\"}]"

and the content of test.sh is the following

#!/bin/bash

#read the json
system_user="$1"

printf "$system_user"

accounts=($(jq -s ".[]" <<< $system_user))

printf "$accounts"

for account in "${accounts[@]}"
do
  printf "\n\n$account\n\n"
done 

the output of -> printf "$system_user" is

[{"username":"user1","password":"pwd1","group":"usergroup1"},{"username":"user2","password":"pwd2","group":"usergroup2"},{"username":"user3","password":"pwd3","group":"usergroup3"}]

but the output of -> printf "$accounts" is something like this

[
[
{
"username":
"user1"
etc. etc. one object for each token :-(

and so on, but what I was expecting is an array of three object (like you can test on jqplay.org)

 {
   "username": "user1",
   "password": "pwd1",
   "group": "usergroup1"
 }
 {
   "username": "user2",
   "password": "pwd2",
   "group": "usergroup2"
 }
 {
   "username": "user3",
   "password": "pwd3",
   "group": "usergroup3"
 }

In this way I can make a foreach on ${accounts[@]}

What I'm doing wrong? Thank you

Upvotes: 1

Views: 1304

Answers (2)

chepner
chepner

Reputation: 531125

With the -c option, you can print each JSON object on a single line, making it easier to populate the array you want.

$ readarray -t arr < <(jq -c '.[]' <<< "[{\"username\":\"user1\",\"password\":\"pwd1\",\"group\":\"usergroup1\"},{\"username\":\"user2\",\"password\":\"pwd2\",\"group\":\"usergroup2\"},{\"username\":\"user3\",\"password\":\"pwd3\",\"group\":\"usergroup3\"}]") 
$ printf "Object: %s\n" "${arr[@]}"
Object: {"username":"user1","password":"pwd1","group":"usergroup1"}
Object: {"username":"user2","password":"pwd2","group":"usergroup2"}
Object: {"username":"user3","password":"pwd3","group":"usergroup3"}

Upvotes: 2

buff
buff

Reputation: 2053

You are interchanging bash arrays and JSON arrays. When you are creating accounts array, bash splits the elements per each whitespace. That's why you don't get what you expect. You can try the following:

declare -A accounts

while IFS="=" read -r key value
do
    accounts[$key]="$value"
done < <(jq -r "to_entries|map(\"\(.key)=\(.value)\")|.[]" <<< $system_user)

for account in "${accounts[@]}"
do
    printf "$account\n"
done

(stolen from here: https://stackoverflow.com/a/26717401/328977)

to get the following output:

{"username":"user1","password":"pwd1","group":"usergroup1"}
{"username":"user2","password":"pwd2","group":"usergroup2"}
{"username":"user3","password":"pwd3","group":"usergroup3"}

Upvotes: 1

Related Questions