In jc version 1.25.7 a new typeset or declare command parser was introduced. This new parser can make exporting bash variables, arrays, and associative arrays to JSON quick and easy.
The typeset or declare bash internal command can show the definition of a single variable, array, or associative array with the -p option. If you don’t specify a variable name, then all variables, arrays, and associative arrays will be displayed:
$ typeset -pdeclare -- BASH="/opt/homebrew/bin/bash"declare -r BASHOPTS="checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath"declare -i BASHPIDdeclare -A BASH_ALIASES=()declare -- BASH_LOADABLES_PATH="/opt/homebrew/lib/bash:/usr/local/lib/bash:/usr/lib/bash:/opt/local/lib/bash:/usr/pkg/lib/bash:/opt/pkg/lib/bash:."declare -ar BASH_VERSINFO=([0]="5" [1]="3" [2]="9" [3]="1" [4]="release" [5]="aarch64-apple-darwin24.6.0")declare -- BASH_VERSION="5.3.9(1)-release"declare -- COLUMNS="80"...
Here’s an example of using the parser to export a regular bash array to JSON:
$ my_array=("apple" "banana" "cherry")$ typeset -p my_array | jc --typeset -p[ { "name": "my_array", "value": [ "apple", "banana", "cherry" ], "type": "array", "readonly": false, "integer": false, "lowercase": false, "uppercase": false, "exported": false }]
As you can see, jc parses the typeset -p output, which includes the variable and array values along with its metadata. You can filter this JSON object down to the value field to only grab the values, but the other metadata might be useful in some situations.
Note that the -p option for jc is only being used to pretty-print the JSON. This would not be needed within a script.
The same technique can be used on bash associative arrays:
$ declare -A user_roles=( ["admin"]="alice" ["manager"]="bob" ["guest"]="charlie")$ typeset -p user_roles | jc --typeset -p[ { "name": "user_roles", "value": { "manager": "bob", "admin": "alice", "guest": "charlie" }, "type": "associative", "readonly": false, "integer": false, "lowercase": false, "uppercase": false, "exported": false }]
Here we see the value field is a normal JSON object with key/value pairs.
Of course we can export all of our bash variables to JSON by not specifying a variable name in our typeset command:
$ typeset -p | jc --typeset -p[ { "name": "BASH", "value": "/opt/homebrew/bin/bash", "type": "variable", "readonly": false, "integer": false, "lowercase": false, "uppercase": false, "exported": false }, { "name": "BASHOPTS", "value": "checkwinsize:cmdhist:complete_fullquote:expand_aliases:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath", "type": "variable", "readonly": true, "integer": false, "lowercase": false, "uppercase": false, "exported": false }, { "name": "BASHPID", "value": null, "type": "variable", "readonly": false, "integer": true, "lowercase": false, "uppercase": false, "exported": false }, ...
Note that the typeset and declare commands format the output literally how the variable is represented internally. For example, values with line feed characters will have a $ character prepended, so you will need to deal with those. One way would be something like this:
$ typeset -p user_rolesdeclare -A user_roles=([linebreak]=$'line\nbreak' [manager]="bob" [admin]="alice" [guest]="charlie" )$ typeset -p user_roles | jc --typeset[ { "name": "user_roles", "value": { "linebreak": "$line\\nbreak", "manager": "bob", "admin": "alice", "guest": "charlie" }, "type": "associative", "readonly": false, "integer": false, "lowercase": false, "uppercase": false, "exported": false }]$ typeset -p user_roles | jc --typeset | echo -e $(jq -r '.[0].value.linebreak[1:]')linebreak
Perhaps a future version of jc can remove the $ character in these situations.
For more information about the new typeset parser, see the documentation.
See also:
- https://stackoverflow.com/questions/44792241/constructing-a-json-object-from-a-bash-associative-array
- https://unix.stackexchange.com/questions/625501/how-to-create-json-from-associative-array
- https://stackoverflow.com/questions/26808855/how-to-format-a-bash-array-as-a-json-array
- https://unix.stackexchange.com/questions/728524/how-to-use-jq-to-convert-an-bash-array-in-command-line-to-json-array