Home > Mobile >  JQ: Modify object that is the result of a filter while keeping the original structure
JQ: Modify object that is the result of a filter while keeping the original structure

Time:11-18

I have the following JSON

Original Data

{
  "myValues": [
    {
      "filterableValue": "x",
      "something": "else"
    },
    {
      "filterableValue": "y",
      "another key": "another value"
    },
    {
      "filterableValue": "z"
    }
  ],
  "foo": "bar"
}

Using JQ I want to add a key value pair to the first (or all) entries in the myValues array, that have the filterableValue=="y". The position/index of these entries inside the myValues array is arbitrary.

Expected Output

The result should have the same structure (still contain both foo and myValues) but have a modified entry where filterableValue=="y".

{
  "myValues": [
    {
      "filterableValue": "x",
      "something": "else"
    },
    {
      "filterableValue": "y",
      "another key": "another value",
      "this": "has been added" // <-- this is the only thing that changed
    },
    {
      "filterableValue": "z"
    }
  ],
  "foo": "bar"
}

What I tried and why it failed

So far I managed to filter the respective array entry and set the value on the filtered output but didn't manage to keep the original structure AND modifiy a filtered entry. My JQ that adds the "this":"has been added" pair but does not contain the original structure is:

.myValues|map(select(.filterableValue=="y"))[0]|.this="has been added" jqplay mwe

Question

How can I modify a filtered entry as above and contain the original structure?

CodePudding user response:

Enclose the whole selector on the LHS within parentheses:

(.myValues[] | select(.filterableValue == "y")).this = "has been added"

Demo

CodePudding user response:

First, let's cleanup

.myValues | map(select(.filterableValue=="y"))[0]

It's better written as

.myValues[] | select(.filterableValue=="y")

Not only is it shorter, it handles the case where there are 0 or 2 matches better.


Then, you just need to change ... | to ( ... ) |=.

( .myValues[] | select(.filterableValue=="y") ) |= ( .this = "has been added" )

Demo

  • Related