Search code examples
jsonbashpipeimmutabilityjq

jq - Add field to child, print parent


Problem: from a json file, read it up from disk and add a field to a child object and print it back to disk.

File:

{
  "name": "api",
  "script": "index.js",
  "instances": "1",
  "env": {
    "PORT": 3000
  },
  "env_production": {
    "PORT": 3000
  }
}

So i've managed to pipe it and add the field:

cat pm2.json | jq --arg key val '. as $parent | .env_production + {"abc": "123"}'

Which returns the child object with the field added. However, I need to update the file on disk. So I also need to print the whole object (the parent).

I can do that by printing it the $parent variable. But I cannot get it to work since it is immutable.

cat pm2.json | jq --arg key val '. as $parent | .env_production + {"abc": "123"}| $parent'

Question: how can I do this so that the $parent variable have the new added field, so that I can pipe it back to the original file?


Solution

  • The best tool to use here is an updating addition operator, +=

    < pm2.json jq '.env_production += {"abc": "123"}'
    

    will output

    {
      "name": "api",
      "script": "index.js",
      "instances": "1",
      "env": {
        "PORT": 3000
      },
      "env_production": {
        "PORT": 3000,
        "abc": "123"
      }
    }
    

    It works out to something similar to

    . + {"env_production": (.env_production + {"abc":"123"})}
    

    except of course it's far simpler :)