Parse json file in bash

LoxBerry 1.4

This shell tool is included in LoxBerry starting with LoxBerry V1.4. If you use that function, set this minimum version in your plugin.cfg.

LoxBerry ships with the tool jq, that can read and edit json files, as well as find values. The tools website is here, and more useful examples are listed here.

Simple examples

Sample json for the following examples

{
  "NOTIFICATION": [
    "MAIL_SYSTEM_ERROR",
    "MAIL_SYSTEM_INFOS"
  ],
  "SMTP": {
    "ACTIVATE_MAIL": "1",
    "CRYPT": 1,
    "EMAIL": "christian@mydomain.com",
    "PORT": "587",
    "SMTPPASS": "Eins, zwei, Polizei",
    "SMTPSERVER": "smtp.mailserver.com"
  }
}

Take note that NOTIFICATION is an array, and SMTP is an object with elements.

Return the value of a key

$ jq '.SMTP.EMAIL' test.json
"christian@mydomain.com"
 
$ jq -r '.SMTP.EMAIL' test.json
christian@mydomain.com
 
$ jq '.NOTIFICATION' test.json
[
  "MAIL_SYSTEM_ERROR",
  "MAIL_SYSTEM_INFOS"
]

Test if an array element exists

$ jq '.NOTIFICATION | contains(["MAIL_SYSTEM_INFOS"])' test.json
true
$ jq '.NOTIFICATION | contains(["nonsense"])' test.json
false

Assign a bash variable with json property

$ port=$(jq -r '.SMTP.PORT' test.json)
$ echo $port
587

Change a value

This is setting "ACTIVATE_MAIL": to "0".

$ jq '.SMTP.ACTIVATE_MAIL = "0"' test.json > testnew.json
$ mv testnew.json test.json

Take special care that you cannot directly replace the original file, as the jq parser operates line by line. Therefore you need to create a new file, and then move it over the old one.

If you would like to change more then one value, you should first change all values and then write the new config to disk (this extends SDCard lifetime).

$ JSON=`jq '.SMTP.ACTIVATE_MAIL = "0"' test.json`
$ JSON=`echo $JSON | jq '.SMTP.MAILADDRESS = "email@loxberry.de"'`
$ JSON=`echo $JSON | jq '.SMTP.MAILFROM = "Max Mustermann"'`
$ echo $JSON | jq "." > testnew.json
$ mv testnew.json test.json

If you would like to use a predefined variable, change the quoting from single to double quotes and escape the double quotes of the json variable:

$ MAILADDRESS = "email@loxberry.de"
$ jq ".SMTP.MAILADDRESS = \"$MAILADDRESS\"" test.json > testnew.json
$ mv testnew.json test.json

Read json file once, get multiple properties

To not read the json file for every single property, you can load the json file into a bash variable, and let process jq from this variable:

(example with LoxBerry's general.json)

# Read the general.json file into variable generaljson
generaljson=$(<$LBSCONFIG/general.json)
 
# Run jq on the generaljson variable
version=$(jq -r '.Base.Version' <<< "$generaljson")
lang=$(jq -r '.Base.Lang' <<< "$generaljson")
echo "Version: $version Language: $lang"