Sigi
Sigi

Reputation: 53

Remove key from json based on condition with jq

I know there is lot of similar solutions, but no one match my case. I've got this json:

{
  "page": 1,
  "per_page": 20,
  "total": 3,
  "saved_objects": [
    {
      "type": "dashboard",
      "id": "f3ea5f20-e773-11ea-8cae-c1046c8b1215"
    },
    {
      "type": "dashboard",
      "id": "5c071f30-e797-11ea-8cae-c1046c8b1215"
    },
    {
      "type": "dashboard",
      "id": "644a15c0-e79d-11ea-8cae-c1046c8b1215"
    }
  ]
}

and if id == "f3ea5f20-e773-11ea-8cae-c1046c8b1215" or id == "5c071f30-e797-11ea-8cae-c1046c8b1215" I want to remove this keys, so output should be:

{
  "page": 1,
  "per_page": 20,
  "total": 3,
  "saved_objects": [
    {
      "type": "dashboard",
      "id": "644a15c0-e79d-11ea-8cae-c1046c8b1215"
    }
  ]
}

I tried:

jq 'select(.saved_objects[].id != "f3ea5f20-e773-11ea-8cae-c1046c8b1215" and .saved_objects[].id != "5c071f30-e797-11ea-8cae-c1046c8b1215")'

and a lot of variations, but nothing worked. What am I doing wrong?

Thank you for help.

Upvotes: 1

Views: 301

Answers (3)

Dmitry
Dmitry

Reputation: 1293

i'm also tempted to publish a solution based on the different approach (jtc), only for awareness of the alternative:

1. the ad-hoc solution would be to purge parents of each found element:

bash $ <file.json jtc -pw'<f3ea5f20-e773-11ea-8cae-c1046c8b1215>[-1]' -w'<5c071f30-e797-11ea-8cae-c1046c8b1215>[-1]'
{
   "page": 1,
   "per_page": 20,
   "saved_objects": [
      {
         "id": "644a15c0-e79d-11ea-8cae-c1046c8b1215",
         "type": "dashboard"
      }
   ],
   "total": 3
}
bash $ 

2. possibly a more convenient approach, where the ids passed as a JSON array:

bash $ ids='["5c071f30-e797-11ea-8cae-c1046c8b1215","f3ea5f20-e773-11ea-8cae-c1046c8b1215"]'
bash $ <file.json jtc -pw'[id]:<I>P:[-1]' -u"$ids" -u'<I>s'
{
   "page": 1,
   "per_page": 20,
   "saved_objects": [
      {
         "id": "644a15c0-e79d-11ea-8cae-c1046c8b1215",
         "type": "dashboard"
      }
   ],
   "total": 3
}
bash $ 

If it's required to make update right into the source file (a.k.a in-place update), then use option -f, like this: jtc -pw'[id]:<I>P:[-1]' -u$ids -u'<I>s' -f file.json

PS. It so happens that I am also a developer of the jtc unix tool

Upvotes: 0

peak
peak

Reputation: 116880

If the blacklist is quite long or should be passed as a parameter, the following approach is worth noting:

["f3ea5f20-e773-11ea-8cae-c1046c8b1215", "5c071f30-e797-11ea-8cae-c1046c8b1215"] as $blacklist
| .saved_objects |= map(select(.id | IN($blacklist[]) | not))

Or even more succinctly:

["f3ea5f20-e773-11ea-8cae-c1046c8b1215", "5c071f30-e797-11ea-8cae-c1046c8b1215"] as $blacklist
| del(.saved_objects[] | select(.id | IN($blacklist[])))

Note also the use of |= in the first approach above.

Upvotes: 0

choroba
choroba

Reputation: 241998

You were close.

jq '.saved_objects=(
        .saved_objects[] |
            select (.id != "f3ea5f20-e773-11ea-8cae-c1046c8b1215"
                    and .id != "5c071f30-e797-11ea-8cae-c1046c8b1215"))
    ' file.json

Upvotes: 1

Related Questions