1

I have an json file as follows below-

{
  "key1": [
    "value1"
  ],
  "key2": [
    "value2"
  ],
  "key3": [
    "value3"
  ],
  "key4": {
    "name": "value4"
  },
  "key5": [
    {
      "field1": "abc",
      "field2": "xyz"
    }
  ]
}

I want to remove field 2 from key5 array and add another field say field3 in key5 array using jq I tried various way but couldn't figure it how to do this in single command. Can you please help . Thanks in advance

3 Answers 3

1

.key5[] |= ( ... ) allows you to modify each element of the array found at .key5.

Therein, we can use the usual commands for deleting and adding fields.

jq '.key5[] |= ( del( .field2 ) | .field3 = "foo" )'

Demo in jqplay

Here's a variation where the value to add is provided as a command-line argument:

jq --arg val foo '.key5[] |= ( del( .field2 ) | .field3 = $val )'
Sign up to request clarification or add additional context in comments.

2 Comments

brillant......!
works like a charm. Thank you so much. it really helped me in understanding how |= works.
0

This assumes that the insert and deletion keys (field2 and field3) are also dynamic, not just the inserted value.

  • Use --arg and --argjson to initialize variables with values from outside the filter, here field2 as a string and {"field3": "new"} as a JSON object
  • Use the update operator |= on the element you want to change, here .key5[].
    • Note: .key5 is an array, not an object, thus it has no fields. But the array does contain objects as its elements. Using .key5[] to access the array elements will update all objects in the array. To update just one of them, say, the first one, use .key[0] instead.
  • Use delpaths to delete a given path, here the top-level field [$delkey].
  • Use simple addition + to add a new key/value pair as object, here $add.
jq --arg delkey 'field2' --argjson addobj '{"field3": "new"}' '
  .key5[] |= delpaths([[$delkey]]) + $addobj
' input.json
{
  "key1": [
    "value1"
  ],
  "key2": [
    "value2"
  ],
  "key3": [
    "value3"
  ],
  "key4": {
    "name": "value4"
  },
  "key5": [
    {
      "field1": "abc",
      "field3": "new"
    }
  ]
}

Demo

If you want to provide the new object's key and value separately, i.e. as strings, not as a pre-composed JSON, you need a third input variable

jq --arg delkey 'field2' --arg addkey 'field3' --arg addval 'new' '
  .key5[] |= (delpaths([[$delkey]]) | .[$addkey] = $addval)
' input.json

Demo

2 Comments

Thanks for the detailed explanation. Since I wanted to check the field1 value before deleting field2 ,I got it working by adding select operation. Thanks a lot for answer.
It's nice to know that we can do .key5[] |= delpaths([["field2"]]) + {field3} and use + to combine two operations to |=. jqplay.org/s/fP_rXo-NYP
0

Try filter:

del(.key5[0].field2) | .key5[0] |= .+{field3:"foo"}

Output:

{
  "key1": [
    "value1"
  ],
  "key2": [
    "value2"
  ],
  "key3": [
    "value3"
  ],
  "key4": {
    "name": "value4"
  },
  "key5": [
    {
      "field1": "abc",
      "field3": "foo"
    }
  ]
}

Demo

https://jqplay.org/s/EB8MpWRxU2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.