Milton Bertachini
Milton Bertachini

Reputation: 626

How to iterate over JSON array with jq?

I'm building a script to download all CodeCommit repositories at once.

REPOS=$(aws codecommit list-repositories)

echo $REPOS | jq -r '.[]' | while read name ; do
    git clone XXX
done

In first line I get all repos JSON like this:

[
  {
    "repositoryName": "repo_a",
    "repositoryId": "XXXXXX"
  },
  {
    "repositoryName": "repo_b",
    "repositoryId": "XXXXXX"
  },
  {
    "repositoryName": "repo_c",
    "repositoryId": "XXXXXX"
  },
  {
    "repositoryName": "repo_d",
    "repositoryId": "XXXXXX"
  }
]

I need simple iterate this json, to get attributes repositoryName and execute git clone for each repository.

But in this example the command jq -r '.[]' don't works.... This return the entire json on each repeat.

Upvotes: 38

Views: 65087

Answers (4)

Milton Bertachini
Milton Bertachini

Reputation: 626

I found the problem..... this command:

REPOS=$(aws codecommit list-repositories)

Returns a json like this:

{
  "repositories": [
  {
    "repositoryName": "repo_a",
    "repositoryId": "XXXXXX"
  },
  {
    "repositoryName": "repo_b",
    "repositoryId": "XXXXXX"
  },
  {
    "repositoryName": "repo_c",
    "repositoryId": "XXXXXX"
  },
  {
    "repositoryName": "repo_d",
    "repositoryId": "XXXXXX"
  }
]
}

I wasn't considering the 'repositories' field in jq.....

This script works fine now:

REPOS=$(aws codecommit list-repositories)

echo $REPOS | jq -r '.repositories[].repositoryName' | while read name ; do
    git clone ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/$name
done

Thank you for support. Have a good day :)

Upvotes: 6

symcbean
symcbean

Reputation: 48387

If you don't want to convert to scalar values:

#!/bin/bash

D='[
{ "name": "first", "is_disabled": false, "scheme": "https", "value": 30 },
{ "name": "second", "is_disabled": true, "scheme": "https", "value": 118 },
{ "name": "third", "is_disabled": false, "scheme": "https", "value": 93 }
]'

LEN=$( echo "$D" | jq '. | length' )

echo "got $LEN elements"
for (( i=0; i<$LEN; i++ )) ; do
        echo "Element $i:"
        echo "$D" | jq ".[$i]"
done

But it's not very efficient.

A quick google turned up this solution:

sample='[{"name":"foo"},{"name":"bar"}]'
for row in $(echo "${sample}" | jq -r '.[] | @base64'); do
    _jq() {
     echo ${row} | base64 --decode | jq -r ${1}
    }
   echo $(_jq '.')
done

Upvotes: 1

dvlcube
dvlcube

Reputation: 1316

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 "${id}=${name}"
done < <(echo "$repositories" | jq -c '.repositories[]')

Upvotes: 13

Cyrus
Cyrus

Reputation: 88979

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

Upvotes: 39

Related Questions