8

Using jq, is it possible to update property value of an object that contains a specific value in some other property?

In the example below I'd like to set the value of the "value" property of all objects that have "keyname" = "foo".

The example .json file looks like this:

"root" : {
  "instances": [
    {
      "name": "1",
      "configs": [
        {
          "keyname": "foo",
          "value": "" // <- update/set this
        },
        {
          "keyname": "barrr",
          "value": "barrrr"
        }
      ]
    },
    {
      "name": "2",
      "configs": [
        {
          "keyname": "foo",
          "value": "" // <- update/set this
        },
        {
          "keyname": "buzzz",
          "value": "buzzz"
        }
      ]
    }
  ]
}

I tried this but in vain, I get an error about array not being a string:

jq '(.root.instances.configs[] | select(.keyname==foo)).value = foo'

1 Answer 1

9

Assuming that your JSON document is well formed, which the example that you show is not as it contains multiple issues:

$ cat file
{
  "root": {
    "instances": [
      {
        "name": "1",
        "configs": [
          {
            "keyname": "foo",
            "value": ""
          },
          {
            "keyname": "barrr",
            "value": "barrrr"
          }
        ]
      },
      {
        "name": "2",
        "configs": [
          {
            "keyname": "foo",
            "value": ""
          },
          {
            "keyname": "buzzz",
            "value": "buzzz"
          }
        ]
      }
    ]
  }
}
$ jq '( .root.instances[].configs[] | select(.keyname == "foo") ).value |= "foo"' file
{
  "root": {
    "instances": [
      {
        "name": "1",
        "configs": [
          {
            "keyname": "foo",
            "value": "foo"
          },
          {
            "keyname": "barrr",
            "value": "barrrr"
          }
        ]
      },
      {
        "name": "2",
        "configs": [
          {
            "keyname": "foo",
            "value": "foo"
          },
          {
            "keyname": "buzzz",
            "value": "buzzz"
          }
        ]
      }
    ]
  }
}

This jq expression updates the value of the .value key to the string foo. The key that is updated is selected from one of the entries in .root.instances[].configs[]. Note that .root.instances is an array and that each .configs entry in each of its elements is also an array. The select() statement tests the .keyname key with the string foo.

Making the query key and new value variable is done as follows:

jq  --arg querykey 'foo' \
    --arg newval 'The train said "choo choo"' \
    '( .root.instances[].configs[] | select(.keyname == $querykey) ).value |= $newval' file

This creates two internal jq variables called $querykey and $newval. Their values will be properly encoded, so that e.g. $newval can contain double quotes, as shown above.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .