4

I'm tryng to iterate over all element contain in the all index. Here is my json string :

{  
   "all":[  
      {  
            "id":"51a"
      },
      {  
            "id":"52b"
      },
      {  
            "id":"53c"
      }
    ]
}

I have tried to iterate with jq :

for id in $(jq '.all.id | keys | .[]' <<< "$json"); do
    echo "$id"
done

But I get this following error :

jq: error (at :9): Cannot index array with string "id"

I expect to get the following output :

51a
52b
53c
1
  • while IFS= read -r id; do ...; done < <(jq ...) is a better way to run that loop. Right now, if you have an id of *, a list of filenames in your current directory will be inserted (among other issues; consider that one a representative example). Commented May 20, 2019 at 13:37

2 Answers 2

2

Like that:

for id in $(jq -r '.all[].id' <<< "$json"); do
    echo "$id"
done

Notice that -r option has to be used if you want to remove double quotes:

 ·   --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. This can be
       useful for making jq filters talk to non-JSON-based
       systems.

The entire script could look like that:

#!/usr/bin/env bash

json='{  
   "all":[  
      {  
            "id":"51a"
      },
      {  
            "id":"52b"
      },
      {  
            "id":"53c"
      }
    ]
}'

for id in $(jq -r '.all[].id' <<< "$json"); do
    echo "$id"
done

But as noted in the comments, for x in $(...) is an antipattern and should not be used: https://mywiki.wooledge.org/DontReadLinesWithFor.

To assign two indices to 2 separate variables:

#!/usr/bin/env bash

json='{
   "all":[
      {
            "id":"51a",
            "name":"Steve"
      },
      {
            "id":"52b",
            "name":"Phoebe"
      },
      {
            "id":"53c",
            "name":"Dino"
      }
    ]
}'

jq -r '.all[] | .id + " " + .name' <<< "$json" |
    while read -r id name; do
        echo id: "$id"
        echo name: "$name"
    done
Sign up to request clarification or add additional context in comments.

13 Comments

Thank you for the answer ! I have found a workaround pastiebin.com/5ce29e47a50c5 but I'm going to use the code in the answer
I'd like to know if it's possible to also extract an other element from the same array. Let's say I have id and name index with their value. How can I extract both ?
@executable: jq is a fairly simple tool. It defines expressions to extract parts of the input, and a syntax to assemble the output. .all[].id is shorthand for .all | .[] | .id, and you want another member in addition to .id. So how should that second member be combined with .id ?
@executable: It could be something like this: for id in $(jq -r '.all[] | .id + " " + .name' <<< "$json"); do
@Arkadiusz Drabczyk Thank you for the answer but is it possible to assign them separatly to variable ?
|
1

and here's an alternative solution based on a walk-path unix tool for JSON: jtc:

bash $ for id in $(jtc -qq -w'[all][:][id]' <<< "$json"); do  echo "$id"; done
51a
52b
53c
bash $ 

PS> Disclosure: I'm the creator of the jtc tool

2 Comments

What's different from jq ?
tools are drastically different. jq is a processor with own DSL with the scope of operations well beyond JSON data model. While jtc is a utility confined to the data model operations only. That difference let coming up with queries to manipulate source jsons a lot easier (but of course it's mho).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.