skip to Main Content

I want to add package dependencies to the package.json file by bash script using jq.

Add new element to existing JSON array with jq

Here is the test script with 5 steps:

#!/bin/bash

add_element_with_jq() {
    
    # step 1: Add a new root element "{}" first
    echo "============= step 1 ================"
    
    echo "{}" > "package.json"
    
    # step 2: Add a "dependencies" sub element to the root element "{}"
    echo "============= step 2 ================"
    # step 3: Add a "foo" package with version "1.1.1" to the "dependencies"
    echo "============= step 3 ================"
    
    jq '. += dependencies {
      "foo": "1.1.1"
    }' "package.json"
    
    echo "=========== step 3 output =================="
    cat "package.json"
    
    # step 4: Add a "bar" package with version "2.2.2" to the "dependencies"
    echo "============= step 4 ================"
    
    jq '.dependencies += 
      "bar": "2.2.2"
    ' "package.json"
    
    # step 5: If the "foo" package already existed, then update to the latest version. Otherwise, add the "foo" package to the dependencies.
    echo "============= step 5 ================"
    
    jq '.dependencies += 
      "foo": "3.3.3"
    ' "package.json"
    
    echo "=========== final output =================="
    cat "package.json"
}

add_element_with_jq

Here is the error:

============= step 1 ================
============= step 2 ================
============= step 3 ================
jq: error: syntax error, unexpected '{', expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
. += dependencies {                  
jq: 1 compile error
=========== step 3 output ==================
{}
============= step 4 ================
jq: error: syntax error, unexpected ':', expecting $end (Unix shell quoting issues?) at <top-level>, line 2:
      "bar": "2.2.2"           
jq: 1 compile error
============= step 5 ================
jq: error: syntax error, unexpected ':', expecting $end (Unix shell quoting issues?) at <top-level>, line 2:
      "foo": "3.3.3"           
jq: 1 compile error
=========== final output ==================
{}

Here is the expected output:

=========== step 3 output ==================
{
  "dependencies": {
    "foo": "1.1.1"
  }
}
=========== final output ==================
{
  "dependencies": {
    "foo": "3.3.3",
    "bar": "2.2.2"
  }
}

What’s wrong in my bash function, and how to fix the jq commands?

2

Answers


  1. The syntax being used (. += dependencies) seems incorrect.

    To add or modify a key in dependencies, use the following syntax:

    jq '.dependencies["foo"]="1.1.1"' "package.json"
    

    This will output the edited contents. Since we cannot pipe back into the file (it is open for reading while jq is being executed), we have to pipe it to a new file and rename it (use the mv command for this).

    jq '.dependencies["foo"]="1.1.1"' "package.json" > package.json.new 
    && mv package.json.new package.json
    
    Login or Signup to reply.
  2. First of all, all you need is this:

    cat <<'.' >package.json
    {
       "dependencies": {
          "foo": "3.3.3",
          "bar": "2.2.2"
       }
    }
    .
    

    But let’s assume you have a reason to break it down into steps.


    The linked answer is about adding to an array. You are not trying to add to an array. To add a key and value to an object, you can simply use

    .object["key"] = value
    

    Therefore, doing one addition at a time, the program would look like the following:

    { } |
    .dependencies = { } |
    .dependencies[ "foo" ] = "3.3.3" |
    .dependencies[ "bar" ] = "2.2.2"
    

    Demo on jqplay.

    As separate calls to jq, we get the following:

    printf '{ }n' |
    jq '.dependencies = { }' |
    jq '.dependencies[ "foo" ] = "3.3.3"' |
    jq '.dependencies[ "bar" ] = "2.2.2"' >package.json
    

    As a single pipeline, these commands are still entangled. To separate them, we will need a temporary file or the sponge command-line utility.

    printf '{ }n'                                          >package.tmp1.json
    jq '.dependencies = { }'              package.tmp1.json >package.tmp2.json
    jq '.dependencies[ "foo" ] = "3.3.3"' package.tmp2.json >package.tmp3.json
    jq '.dependencies[ "bar" ] = "2.2.2"' package.tmp3.json >package.tmp4.json
    
    mv package.tmp4.json package.json
    rm package.tmp{1,2,3}.json
    

    What if you wanted to add .dependencies only if it didn’t already exist? Replace

    .dependencies = { }
    

    with

    .dependencies //= { }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search