Take advantage of the jq utility to edit messages formatted using JSON (JavaScript Object Notation).

I will use JSON sample files from the JSON website.

Prerequisites

Install jq utility to parse JSON files.

$ sudo apt-get install jq

Glossary example

Inspect glossary.json file.

$ cat glossary.json
{
  "glossary": {
    "title": "example glossary",
    "GlossDiv": {
      "title": "S",
      "GlossList": {
        "GlossEntry": {
          "ID": "SGML",
          "SortAs": "SGML",
          "GlossTerm": "Standard Generalized Markup Language",
          "Acronym": "SGML",
          "Abbrev": "ISO 8879:1986",
          "GlossDef": {
            "para": "A meta-markup language, used to create markup languages such as DocBook.",
            "GlossSeeAlso": [
              "GML",
              "XML"
            ]
          },
          "GlossSee": "markup"
        }
      }
    }
  }
}

Modify glossary definition and store JSON document using glossary-new.json file.

$ jq --arg para "A meta-markup language, used to create markup languages such as a DocBook." '.glossary.GlossDiv.GlossList.GlossEntry.GlossDef.para = $para' glossary.json | tee glossary-new.json
{
  "glossary": {
    "title": "example glossary",
    "GlossDiv": {
      "title": "S",
      "GlossList": {
        "GlossEntry": {
          "ID": "SGML",
          "SortAs": "SGML",
          "GlossTerm": "Standard Generalized Markup Language",
          "Acronym": "SGML",
          "Abbrev": "ISO 8879:1986",
          "GlossDef": {
            "para": "A meta-markup language, used to create markup languages such as a DocBook.",
            "GlossSeeAlso": [
              "GML",
              "XML"
            ]
          },
          "GlossSee": "markup"
        }
      }
    }
  }
}

Compare differences between these JSON documents.

$ diff -u glossary.json glossary-new.json
--- glossary.json	2020-03-23 00:12:36.650206560 +0100
+++ glossary-new.json	2020-03-23 00:14:55.895840579 +0100
@@ -11,7 +11,7 @@
           "Acronym": "SGML",
           "Abbrev": "ISO 8879:1986",
           "GlossDef": {
-            "para": "A meta-markup language, used to create markup languages such as DocBook.",
+            "para": "A meta-markup language, used to create markup languages such as a DocBook.",
             "GlossSeeAlso": [
               "GML",
               "XML"

Alternatively, use jq utility to inspect differences between JSON documents.

$ diff <(jq '.' glossary.json) <(jq --arg para "A meta-markup language, used to create markup languages such as a DocBook." '.glossary.GlossDiv.GlossList.GlossEntry.GlossDef.para = $para' glossary.json)
14c14
<             "para": "A meta-markup language, used to create markup languages such as DocBook.",
---
>             "para": "A meta-markup language, used to create markup languages such as a DocBook.",

Overwrite original file.

$ mv glossary-new.json glossary.json

Inspect menu.json file.

$ cat menu.json
{
  "menu": {
    "header": "SVG Viewer",
    "items": [
      {
        "id": "Open"
      },
      {
        "id": "OpenNew",
        "label": "Open New"
      },
      null,
      {
        "id": "ZoomIn",
        "label": "Zoom In"
      },
      {
        "id": "ZoomOut",
        "label": "Zoom Out"
      },
      {
        "id": "OriginalView",
        "label": "Original View"
      },
      null,
      {
        "id": "Quality"
      },
      {
        "id": "Pause"
      },
      {
        "id": "Mute"
      },
      null,
      {
        "id": "Find",
        "label": "Find..."
      },
      {
        "id": "FindAgain",
        "label": "Find Again"
      },
      {
        "id": "Copy"
      },
      {
        "id": "CopyAgain",
        "label": "Copy Again"
      },
      {
        "id": "CopySVG",
        "label": "Copy SVG"
      },
      {
        "id": "ViewSVG",
        "label": "View SVG"
      },
      {
        "id": "ViewSource",
        "label": "View Source"
      },
      {
        "id": "SaveAs",
        "label": "Save As"
      },
      null,
      {
        "id": "Help"
      },
      {
        "id": "About",
        "label": "About Adobe CVG Viewer..."
      }
    ]
  }
}

Modify specific menu item and store JSON document using menu-new.json file.

$ jq --arg id "Find" --arg value "Find"  '.menu.items=([.menu.items[] | select(.id == $id) .label = $value ])' menu.json | tee menu-new.json
{
  "menu": {
    "header": "SVG Viewer",
    "items": [
      {
        "id": "Open"
      },
      {
        "id": "OpenNew",
        "label": "Open New"
      },
      null,
      {
        "id": "ZoomIn",
        "label": "Zoom In"
      },
      {
        "id": "ZoomOut",
        "label": "Zoom Out"
      },
      {
        "id": "OriginalView",
        "label": "Original View"
      },
      null,
      {
        "id": "Quality"
      },
      {
        "id": "Pause"
      },
      {
        "id": "Mute"
      },
      null,
      {
        "id": "Find",
        "label": "Find"
      },
      {
        "id": "FindAgain",
        "label": "Find Again"
      },
      {
        "id": "Copy"
      },
      {
        "id": "CopyAgain",
        "label": "Copy Again"
      },
      {
        "id": "CopySVG",
        "label": "Copy SVG"
      },
      {
        "id": "ViewSVG",
        "label": "View SVG"
      },
      {
        "id": "ViewSource",
        "label": "View Source"
      },
      {
        "id": "SaveAs",
        "label": "Save As"
      },
      null,
      {
        "id": "Help"
      },
      {
        "id": "About",
        "label": "About Adobe CVG Viewer..."
      }
    ]
  }
}

Compare differences between these JSON documents.

$ diff -u menu.json menu-new.json
--- menu.json	2020-03-23 00:29:49.458740165 +0100
+++ menu-new.json	2020-03-23 00:31:24.877504701 +0100
@@ -35,7 +35,7 @@
       null,
       {
         "id": "Find",
-        "label": "Find..."
+        "label": "Find"
       },
       {
         "id": "FindAgain",

Overwrite original file.

$ mv menu-new.json menu.json

Web-app example

Inspect web-app.json file.

$ cat web-app.json
{
  "web-app": {
    "servlet": [
      {
        "servlet-name": "cofaxCDS",
        "servlet-class": "org.cofax.cds.CDSServlet",
        "init-param": {
          "configGlossary:installationAt": "Philadelphia, PA",
          "configGlossary:adminEmail": "ksm@pobox.com",
          "configGlossary:poweredBy": "Cofax",
          "configGlossary:poweredByIcon": "/images/cofax.gif",
          "configGlossary:staticPath": "/content/static",
          "templateProcessorClass": "org.cofax.WysiwygTemplate",
          "templateLoaderClass": "org.cofax.FilesTemplateLoader",
          "templatePath": "templates",
          "templateOverridePath": "",
          "defaultListTemplate": "listTemplate.htm",
          "defaultFileTemplate": "articleTemplate.htm",
          "useJSP": false,
          "jspListTemplate": "listTemplate.jsp",
          "jspFileTemplate": "articleTemplate.jsp",
          "cachePackageTagsTrack": 200,
          "cachePackageTagsStore": 200,
          "cachePackageTagsRefresh": 60,
          "cacheTemplatesTrack": 100,
          "cacheTemplatesStore": 50,
          "cacheTemplatesRefresh": 15,
          "cachePagesTrack": 200,
          "cachePagesStore": 100,
          "cachePagesRefresh": 10,
          "cachePagesDirtyRead": 10,
          "searchEngineListTemplate": "forSearchEnginesList.htm",
          "searchEngineFileTemplate": "forSearchEngines.htm",
          "searchEngineRobotsDb": "WEB-INF/robots.db",
          "useDataStore": true,
          "dataStoreClass": "org.cofax.SqlDataStore",
          "redirectionClass": "org.cofax.SqlRedirection",
          "dataStoreName": "cofax",
          "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
          "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
          "dataStoreUser": "sa",
          "dataStorePassword": "dataStoreTestQuery",
          "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
          "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
          "dataStoreInitConns": 10,
          "dataStoreMaxConns": 100,
          "dataStoreConnUsageLimit": 100,
          "dataStoreLogLevel": "debug",
          "maxUrlLength": 500
        }
      },
      {
        "servlet-name": "cofaxEmail",
        "servlet-class": "org.cofax.cds.EmailServlet",
        "init-param": {
          "mailHost": "mail1",
          "mailHostOverride": "mail2"
        }
      },
      {
        "servlet-name": "cofaxAdmin",
        "servlet-class": "org.cofax.cds.AdminServlet"
      },
      {
        "servlet-name": "fileServlet",
        "servlet-class": "org.cofax.cds.FileServlet"
      },
      {
        "servlet-name": "cofaxTools",
        "servlet-class": "org.cofax.cms.CofaxToolsServlet",
        "init-param": {
          "templatePath": "toolstemplates/",
          "log": 1,
          "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
          "logMaxSize": "",
          "dataLog": 1,
          "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
          "dataLogMaxSize": "",
          "removePageCache": "/content/admin/remove?cache=pages&id=",
          "removeTemplateCache": "/content/admin/remove?cache=templates&id=",
          "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
          "lookInContext": 1,
          "adminGroupID": 4,
          "betaServer": true
        }
      }
    ],
    "servlet-mapping": {
      "cofaxCDS": "/",
      "cofaxEmail": "/cofaxutil/aemail/*",
      "cofaxAdmin": "/admin/*",
      "fileServlet": "/static/*",
      "cofaxTools": "/tools/*"
    },
    "taglib": {
      "taglib-uri": "cofax.tld",
      "taglib-location": "/WEB-INF/tlds/cofax.tld"
    }
  }
}

Modify specific parameter and store JSON document using web-app-new.json file.

$ jq --arg id "cofaxTools" --arg logSize 300  '.["web-app"].servlet |= map((select(.["servlet-name"] == $id) | .["init-param"].logMaxSize = $logSize) // .) ' web-app.json | tee web-app-new.json
{
  "web-app": {
    "servlet": [
      {
        "servlet-name": "cofaxCDS",
        "servlet-class": "org.cofax.cds.CDSServlet",
        "init-param": {
          "configGlossary:installationAt": "Philadelphia, PA",
          "configGlossary:adminEmail": "ksm@pobox.com",
          "configGlossary:poweredBy": "Cofax",
          "configGlossary:poweredByIcon": "/images/cofax.gif",
          "configGlossary:staticPath": "/content/static",
          "templateProcessorClass": "org.cofax.WysiwygTemplate",
          "templateLoaderClass": "org.cofax.FilesTemplateLoader",
          "templatePath": "templates",
          "templateOverridePath": "",
          "defaultListTemplate": "listTemplate.htm",
          "defaultFileTemplate": "articleTemplate.htm",
          "useJSP": false,
          "jspListTemplate": "listTemplate.jsp",
          "jspFileTemplate": "articleTemplate.jsp",
          "cachePackageTagsTrack": 200,
          "cachePackageTagsStore": 200,
          "cachePackageTagsRefresh": 60,
          "cacheTemplatesTrack": 100,
          "cacheTemplatesStore": 50,
          "cacheTemplatesRefresh": 15,
          "cachePagesTrack": 200,
          "cachePagesStore": 100,
          "cachePagesRefresh": 10,
          "cachePagesDirtyRead": 10,
          "searchEngineListTemplate": "forSearchEnginesList.htm",
          "searchEngineFileTemplate": "forSearchEngines.htm",
          "searchEngineRobotsDb": "WEB-INF/robots.db",
          "useDataStore": true,
          "dataStoreClass": "org.cofax.SqlDataStore",
          "redirectionClass": "org.cofax.SqlRedirection",
          "dataStoreName": "cofax",
          "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
          "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
          "dataStoreUser": "sa",
          "dataStorePassword": "dataStoreTestQuery",
          "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
          "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
          "dataStoreInitConns": 10,
          "dataStoreMaxConns": 100,
          "dataStoreConnUsageLimit": 100,
          "dataStoreLogLevel": "debug",
          "maxUrlLength": 500
        }
      },
      {
        "servlet-name": "cofaxEmail",
        "servlet-class": "org.cofax.cds.EmailServlet",
        "init-param": {
          "mailHost": "mail1",
          "mailHostOverride": "mail2"
        }
      },
      {
        "servlet-name": "cofaxAdmin",
        "servlet-class": "org.cofax.cds.AdminServlet"
      },
      {
        "servlet-name": "fileServlet",
        "servlet-class": "org.cofax.cds.FileServlet"
      },
      {
        "servlet-name": "cofaxTools",
        "servlet-class": "org.cofax.cms.CofaxToolsServlet",
        "init-param": {
          "templatePath": "toolstemplates/",
          "log": 1,
          "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
          "logMaxSize": "300",
          "dataLog": 1,
          "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
          "dataLogMaxSize": "",
          "removePageCache": "/content/admin/remove?cache=pages&id=",
          "removeTemplateCache": "/content/admin/remove?cache=templates&id=",
          "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
          "lookInContext": 1,
          "adminGroupID": 4,
          "betaServer": true
        }
      }
    ],
    "servlet-mapping": {
      "cofaxCDS": "/",
      "cofaxEmail": "/cofaxutil/aemail/*",
      "cofaxAdmin": "/admin/*",
      "fileServlet": "/static/*",
      "cofaxTools": "/tools/*"
    },
    "taglib": {
      "taglib-uri": "cofax.tld",
      "taglib-location": "/WEB-INF/tlds/cofax.tld"
    }
  }
}

Compare differences between these JSON documents.

$ diff -u web-app.json web-app-new.json
--- web-app.json	2020-03-23 00:54:56.465361339 +0100
+++ web-app-new.json	2020-03-23 01:24:46.150890321 +0100
@@ -72,7 +72,7 @@
           "templatePath": "toolstemplates/",
           "log": 1,
           "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
-          "logMaxSize": "",
+          "logMaxSize": "300",
           "dataLog": 1,
           "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
           "dataLogMaxSize": "",

Overwrite original file.

$ mv web-app-new.json web-app.json

Widget example

Inspect widget.json file.

$ cat widget.json
{
  "widget": {
    "debug": "on",
    "window": {
      "title": "Sample Konfabulator Widget",
      "name": "main_window",
      "width": 500,
      "height": 500
    },
    "image": {
      "src": "Images/Sun.png",
      "name": "sun1",
      "hOffset": 250,
      "vOffset": 250,
      "alignment": "center"
    },
    "text": {
      "data": "Click Here",
      "size": 36,
      "style": "bold",
      "name": "text1",
      "hOffset": 250,
      "vOffset": 100,
      "alignment": "center",
      "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
    }
  }
}

Modify multiple widget elements and store JSON document using widget-new.json file.

$ jq '.widget = (.widget | .debug = "off" | .image.comment = "Sun image" | .text.size=38)' widget.json | tee widget-new.json
{
  "widget": {
    "debug": "off",
    "window": {
      "title": "Sample Konfabulator Widget",
      "name": "main_window",
      "width": 500,
      "height": 500
    },
    "image": {
      "src": "Images/Sun.png",
      "name": "sun1",
      "hOffset": 250,
      "vOffset": 250,
      "alignment": "center",
      "comment": "Sun image"
    },
    "text": {
      "data": "Click Here",
      "size": 38,
      "style": "bold",
      "name": "text1",
      "hOffset": 250,
      "vOffset": 100,
      "alignment": "center",
      "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
    }
  }
}

Compare differences between these JSON documents.

$ diff -u widget.json  widget-new.json
--- widget.json	2020-03-23 01:30:13.078389165 +0100
+++ widget-new.json	2020-03-23 01:36:20.812056381 +0100
@@ -1,6 +1,6 @@
 {
   "widget": {
-    "debug": "on",
+    "debug": "off",
     "window": {
       "title": "Sample Konfabulator Widget",
       "name": "main_window",
@@ -12,11 +12,12 @@
       "name": "sun1",
       "hOffset": 250,
       "vOffset": 250,
-      "alignment": "center"
+      "alignment": "center",
+      "comment": "Sun image"
     },
     "text": {
       "data": "Click Here",
-      "size": 36,
+      "size": 38,
       "style": "bold",
       "name": "text1",
       "hOffset": 250,

Overwrite original file.

$ mv widget-new.json widget.json

Additional information

JSON Example

Modify properties on selected objects #738

Cannot select field if field name has dashes #38