user10663015
user10663015

Reputation:

Loop json Output in shell script

I have this output variable

OUTPUT=$(echo $ZONE_LIST  | jq -r '.response | .data[]')

The Output:

{
  "accountId": "xyz",
  "addDate": "2020-09-05T10:57:11Z",
  "content": "\"MyContent\"",
  "id": "MyID",
  "priority": null
}
{
  "accountId": "xyz",
  "addDate": "2020-09-05T06:58:52Z",
  "content": "\"MyContent\"",
  "id": "MyID",
  "priority": null
}

How can I create a loop for this two values?

MyLoop
  echo "$content - $id"
done

I tried this, but then I get a loop through every single value

for k in $(echo $ZONE_LIST  | jq -r '.response | .data[]'); do
    echo $k
done

EDIT 1:

My complete JSON:

{
    "errors": [],
    "metadata": {
        "transactionId": "",
    },
    "response": {
        "data": [
            {
                "accountId": "xyz",
                "addDate": "2020-09-05T10:57:11Z",
                "content": "\"abcd\"",
                "id": "myID1",
                "lastChangeDate": "2020-09-05T10:57:11Z",
            },
            {
                "accountId": "xyz",
                "addDate": "2020-09-05T06:58:52Z",
                "content": "\"abc\"",
                "id": "myID2",
                "lastChangeDate": "2020-09-05T07:08:15Z",
            }
        ],
        "limit": 10,
        "page": 1,
        "totalEntries": 2,
    },
    "status": "success",
    "warnings": []
}

Now I need a loop for data, because I need it for a curl

The curl NOW:

curl -s -v -X POST --data '{
    "deleteEntries": [
        Data_from_json
    ]
}' https://URL_to_Update 2>/dev/null)

Now I want to create a new variable from my JSON data. My CURL should look like this at the end:

curl -s -v -X POST --data '{
    "deleteEntries": [
        {
            "readID": "myID1",
            "date": "2020-09-05T10:57:11Z", <--Value from addDate
            "content": "abcd"
        },
        {
            "readID": "myID2",
            "date": "2020-09-05T06:58:52Z", <--Value from addDate
            "content": "abc"
        }
    ]
}' https://URL_to_Update 2>/dev/null)

Upvotes: 1

Views: 633

Answers (3)

David Medinets
David Medinets

Reputation: 5618

The first step is to realize you can turn the set of fields into an array like this using a technique like this:

jq '(.accountId + "," + .addDate)'

Now you can update your bash loop:

for k in $(echo $ZONE_LIST  | jq -r '.response | .data[]' | jq '(.content + "," + .id)'); do
    echo $k
done

There is probably a way to combine the two jq commands but I don't have your original json data for testing.

UPDATE - inside the loop you can parse the comma-delimited string into separate fields. This are more efficient ways to handle this task but I prefer simplicity.

    ID=$(echo $k | cut -d',' -f1)
    PRIORITY=$(echo $k | cut -d',' -f2)
    echo "ID($ID)  PRIORITY($PRIORITY)"

Upvotes: 0

fmer
fmer

Reputation: 14

Try this.

for k in $(echo $ZONE_LIST  | jq -rc '.response | .data[]'); do
    echo $k|jq '.content + " - " + .id' -r
done

Upvotes: -1

L&#233;a Gris
L&#233;a Gris

Reputation: 19675

Something like:

#!/usr/bin/env bash
while IFS=$'\37' read -r -d '' id content; do
  echo "$id" "$content"
done < <(
  jq -j '.response | .data[] | .id + "\u001f" + .content + "\u0000"' \
  <<<"$ZONE_LIST"
)
  • jq -j: Forces a raw output from jq.
  • .id + "\u001f" + .content + "\u0000": Assemble fields delimited by ASCII FS (Hexadecimal 1f or Octal 37), and end record by a null character.

It then becomes easy and reliable to iterate over null delimited records by having read -d '' (null delimiter).

Fields id content are separated by ASCII FS, so just set the Internal Field Separator IFS environment variable to the corresponding octal IFS=$'37' before reading.

Upvotes: 1

Related Questions