JQ edit file in place after using JQ Select
Asked Answered
S

1

6

to edit a json file inplace with JQ like -i in sed I have found many solutions like

jq ... input.json > tmp.json && mv tmp.json input.json

This works, but I need to filter on my file, add some data, and place it back in the original. (ie. Update a specific object in a file)

My file contains over 1000 objects with different Element. I will always be using a filter on Element, I shortened for question. I have a sample file original.json ...

{
  "Element": "acton",
  "objectName": "contacts",
  "Path": "/contacts",
  "Scenario": "",
  "serviceLevel": "",
  "IBM": "",
  "Gap": "",
  "clientPhase": "",
  "parentPhase": "",
  "existsToday": ""
}
{
  "Element": "acton",
  "objectName": "optouts",
  "Path": "/optouts",
  "Scenario": "",
  "serviceLevel": "",
  "IBM": "",
  "Dependency": "",
  "Gap": "",
  "clientPhase": "",
  "parentPhase": "",
  "existsToday": ""
}
{
  "Element": "acton",
  "objectName": "subscriptionTypes",
  "Path": "/subscription-types",
  "Scenario": "",
  "serviceLevel": "",
  "IBM": "",
  "Dependency": "",
  "Gap": "",
  "clientPhase": "",
  "parentPhase": "",
  "existsToday": ""
}

I want to filter by objectName for contacts add some data to empty IBM field and save to the file

Applying the same logic to inplace edit the IBM field to "Y" on object containing "objectName": "contacts"

jq 'select(.objectName == "contacts") | .IBM = "Y"' original.json > tmpjson.json && mv tmpjson.json original.json

Now my file original.json shows

{
  "Element": "acton",
  "objectName": "contacts",
  "Path": "/contacts",
  "Scenario": "",
  "serviceLevel": "",
  "IBM": "Y",
  "Dependency": "",
  "Gap": "",
  "clientPhase": "",
  "parentPhase": "",
  "existsToday": ""
}

Expected Result

{
  "Element": "acton",
  "objectName": "contacts",
  "Path": "/contacts",
  "Scenario": "",
  "serviceLevel": "",
  "IBM": "Y",
  "Gap": "",
  "clientPhase": "",
  "parentPhase": "",
  "existsToday": ""
}
{
  "Element": "acton",
  "objectName": "optouts",
  "Path": "/optouts",
  "Scenario": "",
  "serviceLevel": "",
  "IBM": "",
  "Dependency": "",
  "Gap": "",
  "clientPhase": "",
  "parentPhase": "",
  "existsToday": ""
}
{
  "Element": "acton",
  "objectName": "subscriptionTypes",
  "Path": "/subscription-types",
  "Scenario": "",
  "serviceLevel": "",
  "IBM": "",
  "Dependency": "",
  "Gap": "",
  "clientPhase": "",
  "parentPhase": "",
  "existsToday": ""
}

It seems after using select I can no longer use the provided solution https://github.com/stedolan/jq/wiki/FAQ#general-questions

Superclass answered 20/2, 2018 at 4:45 Comment(1)
@peak I know has a knack for these questionsSuperclass
C
19

Your jq filter is not the one you need because select selects. That is, it filters out the objects that don't match the selection criterion.

This jq filter should do what you want:

if (.objectName == "contacts") then .IBM = "Y" else . end

As for overwriting the file, many people who have access to sponge (part of the moreutils collection of CLI utilities) use it, e.g.

jq 'if (.objectName == "contacts") then .IBM = "Y" else . end' input.json |
  sponge input.json
Coolth answered 20/2, 2018 at 4:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.