Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQ edit file in place after using JQ Select

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

like image 809
Goldfish Avatar asked Dec 04 '22 20:12

Goldfish


1 Answers

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
like image 75
peak Avatar answered Dec 06 '22 11:12

peak