Friday, October 7, 2022

[SOLVED] JQ Loop over Bash array add elements

Issue

I do not seem to be able to find an answer, but have seen enough to know there is likely a better way of doing what I want to do.

Problem: I have a bash array. For each element in the bash array, I want to update a JSON array.

The JSON looks like the below. I am wanting to update the fruit array.

  "foods": {
    "perishable": {
      "fruit": []

I'll get an array of length n, for example:

fruit_array=("banana" "orange")

It should look something like this:

  "foods": {
    "perishable": {
      "fruit": [
        { 
          "001": {
            "002": "banana"
          }
        },
        { 
          "001": {
            "002": "orange"
          }
        }
      ]

Is there a nice way of doing this? At the moment I am trying the below:

#!/bin/bash

fruit_array=("banana" "orange")

for fruit in "${fruit_array[@]}"; do
   jq \
   --arg fruit $fruit \
   '.foods.perishables.fruit += [{"001": {"002": $fruit}}]' \
   template.json > template_with_fruit.json
done

This doesn't work for the obvious reason that the template is being re-read, but I have messed around to get it consuming the output of the previous iteration and nothing comes out at the end. I am only able to update the template once.

However, I know this seems a little dodgy and suspect there is a cleaner, more jq way.

A previous - aborted - attempt went something like this:

jq \
--argjson fruit "$(printf '{"001": {"002": "%s"}}\n' \"${fruit_array[@]}\" | jq -nR '[inputs]')" \
'.foods.perishables.fruit += $fruit' \

Which produced a escaped string which I couldn't do anything with, but at least hinted that there might be a neater solution to the standard bash loop.

I am missing something.

Any help would, as always, be appreciated.


Solution

JQ can do all that on its own; you don't need a loop or anything.

jq '.foods.perishable.fruit += (
  $ARGS.positional
  | map({"001": {"002": .}})
)' template.json --args "${fruit_array[@]}" >template_with_fruit.json


Answered By - oguz ismail
Answer Checked By - Marilyn (WPSolving Volunteer)