ITL ITL - 1 month ago 7
JSON Question

Replace array element within JSON hash with content from other file

I have got a configuration with content to be exchanged with snippets from separate file. How would I neatly achieve this?

Config file might look like:

# config file
{
"keep": "whatever type of value",
"manipulate": [
{
"foo": "bar",
"cat": {
"color": "grey"
},
"type": "keep",
"detail": "keep whole array element"
},
{
"stuff": "obsolete",
"more_stuff": "obsolete",
"type": "replace",
"detail": "replace whole array element with content from separate file"
},
{
"foz": "baz",
"dog": {
"color": "brown"
},
"type": "keep",
"detail": "keep whole array element"
},

],
"also_keep": "whatever type of value"
}


The content (coming from separate file) to be inserted as a replacement of obsolete array element:

# replacement
{
"stuff": "i want that",
"fancy": "very",
"type": "new"
}


The desired result should look like:

# result
{
"keep": "whatever kind of value",
"manipulate": [
{
"foo": "bar",
"cat": {
"color": "grey"
},
"type": "keep",
"detail": "keep whole array element"
},
{
"stuff": "i want that",
"fancy": "very",
"type": "new"
},
{
"foz": "baz",
"dog": {
"color": "brown"
},
"type": "keep",
"detail": "keep whole array element"
},

],
"also_keep": "whatever kind of value",
}


Requirements:


  • Content replacement needs to be done based on
    type
    key's value.

  • Preferably use
    jq
    and common bash/linux tools.

  • Array element ordering should stay same


Answer Source

jq solution:

jq --slurpfile repl repl.json '.manipulate=[.manipulate[] 
     | if .type=="replace" then .=$repl[0] else . end]' config.json
  • repl.json - json file containing replacement JSON data

  • --slurpfile repl repl.json - reads all the JSON texts in the named file and binds an array of the parsed JSON values to the given global variable

The output:

{
  "keep": "whatever type of value",
  "manipulate": [
    {
      "foo": "bar",
      "cat": {
        "color": "grey"
      },
      "type": "keep",
      "detail": "keep whole array element"
    },
    {
      "stuff": "i want that",
      "fancy": "very",
      "type": "new"
    },
    {
      "foz": "baz",
      "dog": {
        "color": "brown"
      },
      "type": "keep",
      "detail": "keep whole array element"
    }
  ],
  "also_keep": "whatever type of value"
}