Saravanan A
Saravanan A

Reputation: 11

JQ - how to insert in middle of an array object through jq

Can you hint on how to insert a new element in middle of an array object through jq..

1.json file :-

[ {
    "name": "Dependencies",
    "asyncInstallation": false,
    "failOnError": true,
    "yamls": [
      "dependency.yaml",
          ]
  },
  {
    "name": "Management Configuration",
    "asyncInstallation": false,
    "failOnError": true,
    "yamls": [
      "mgmt-job.yaml"
    ]
  },
  {
    "name": "Data Configuration",
    "asyncInstallation": false,
    "failOnError": true,
    "yamls": [
      "data-job.yaml"
    ]
  }, 
  {
    "name": "Tools",
    "asyncInstallation": true,
    "failOnError": false,
    "yamls": [
      "tools-job.yaml"
    ]
  }
]

I would like to insert the following text post Management Configuration.

 {
    "name": "NEW Configuration",
    "asyncInstallation": false,
    "failOnError": true,
    "yamls": [
      "newfile.yaml"
    ]
  }, 

Can you please suggest how can we do by using jq or sed ?

thanks saravanan

Upvotes: 1

Views: 718

Answers (2)

Jeff Mercado
Jeff Mercado

Reputation: 134521

You could use map/1 to perform the insertion. In the mapping, you could check if you're currently at the node you want to insert after and output it and the new node you wish to insert, otherwise make no further modifications.

$ jq --argjson i '...' 'map(if .name == "Management Configuration" then ., $i else . end)'

Upvotes: 0

peak
peak

Reputation: 116880

First, let's suppose we knew the index of the object with name "Management Configuration" was $i. Then, assuming the object to be inserted is $o, we would write:

.[0:$i+1] + [$o] + .[$i+1:]

So the task boils down to finding $i, which can be done efficiently as follows:

first(range(0;length) as $i
      | select(.[$i].name=="Management Configuration")
      | $i)

Taking care to ensure we handle the possibility that the object we expect to occur in the array does not, we can put the pieces together as follows:

(first(range(0;length) as $i
 | select(.[$i].name=="Management Configuration")
 | $i) // null) as $i
| if $i then .[0:$i+1] + [$o] + .[$i+1:] else . end

One way to set $o would be on the command line, e.g. along the lines of:

jq --argjson o '....' -f insert.jq 1.json

indexof

It might make sense to use the following generic def:

def indexof(f):
  first(range(0;length) as $i
        | select(.[$i]|f) | $i) // null;

The solution then becomes:

indexof(.name=="Management Configuration") as $i
| if $i then .[0:$i+1] + [$o] + .[$i+1:] else . end

Upvotes: 5

Related Questions