Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically add json object into array with jq

Below is the template of my employee.json file

{
    "orgConfig": {
        "departments": []
    }
}

where departments will have array of departments like below

{
    "name" : "physics",
    "id" : "1234",
    "head" : "abcd"
}

similarly

{
    "name" : "chemistry",
    "id" : "3421",
    "head" : "xyz"
}

so the final array structure i want to construct is as below

{
    "orgConfig": {
        "departments": [
            {
                "name" : "physics",
                "id" : "1234",
                "head" : "abcd"
            },
            {
                "name" : "chemistry",
                "id" : "3421",
                "head" : "xyz"
            },
            {
                "name" : "Maths",
                "id" : "4634",
                "head" : "jklm"
            }
        ]
    }
}

Below is the code where i am adding the json elements to an departments array dynamically

#!/bin/bash

source department.properties   # will have departments=physiscs,chemistry,Maths,computers .. etc
IFS=',' read -ra NAMES <<< "$departmentsToImport"

position=0
for i in "${NAMES[@]}"; do
    #./jsonfiles will chemistry.json, physics.json, Maths.json etc
    value=`cat ./jsonfiles/$i.json`    

    if [ $position -eq 0 ]
    then
       cat employee.json | jq --arg value "$value" '.orgConfig.departments[0] |= .+ $value' > tmp.json && mv tmp.json employee.json
    else
       cat employee.json | jq --arg position "$position" value "$value" '.orgConfig.departments[$position] |= .+ $value' > tmp.json && mv tmp.json employee.json
    fi
    ((position++))
    rm -rf tmp.json
done

exit $?

but program throws below error

jq: error (at <stdin>:51): Cannot index array with string "1"

But if use direct index instead of variable position then it works fine.

cat employee.json | jq --argjson value "$value" '.orgConfig.departments[1] |= .+ $value' > tmp.json && mv tmp.json employee.json 

I do not know how many key value maps of departments i have. I cannot hard code the index. Any help to above problem and Dynamically add json object into array?

Thanks

like image 215
user1876040 Avatar asked Mar 09 '23 14:03

user1876040


1 Answers

This can be done by turning off jq's automatic input reading, then piping the first explicit input through a filter that modifies its input using the remaining explicit inputs. Make sense? No :) But the code itself is simple:

jq -n 'input | .orgConfig.departments += [inputs]' \
  employee.json chemistry.json physics.json math.json
  1. The first input reads from the first argument (employee.json).
  2. The += gets its input from the input filter. Its left operand selects the field to update; the right operand provides the value to update it with.
  3. inputs reads from the remaining command-line arguments, and puts their contents in an array, each file in a separate element.

Combining this with your shell code to select the correct course files yields

source department.properties
IFS=, read -ra NAMES <<< "$departmentsToImport"
for c in "${NAMES[@]}"; do
    courses+=("./jsonfiles/$c.json")
done
jq -n 'input | .orgConfig.departments += [inputs]' employee.json "${courses[@]}"
like image 168
chepner Avatar answered Mar 20 '23 04:03

chepner