How to format bash array as JSON array
I have a bash array
X=("hello world" "goodnight moon")
What i want to turn into json array
["hello world", "goodnight moon"]
Is there a good way to turn this into a json array of strings without skewing over the keys in a subshell?
(for x in "${X[@]}"; do; echo $x | sed 's|.*|"&"|'; done) | jq -s '.'
This clearly doesn't work
echo "${X[@]}" | jq -s -R '.'
source to share
It...
X=("hello world" "goodnight moon" 'say "boo"' 'foo\bar')
json_array() {
echo -n '['
while [ $# -gt 0 ]; do
x=${1//\\/\\\\}
echo -n \"${x//\"/\\\"}\"
[ $# -gt 1 ] && echo -n ', '
shift
done
echo ']'
}
json_array "${X[@]}"
... gives:
["hello world", "goodnight moon", "say \"boo\"", "foo\\bar"]
If you plan on doing this a lot (as you are not encouraged to use a hint), then something like this that does not depend on any subprocess will most likely be useful to you.
source to share
If the values ββdo not contain ASCII control characters, which must be escaped in strings in valid JSON, you can also use sed
:
$ X=("hello world" "goodnight moon") $ printf %s\\n "${X[@]}"|sed 's/["\]/\\&/g;s/.*/"&"/;1s/^/[/;$s/$/]/;$!s/$/,/' ["hello world", "goodnight moon"]
If the values ββcontain ASCII control characters, you can do something like this:
X=($'a\ta' $'a\n\\\"') for((i=0;i<${#X[@]};i++));do [ $i = 0 ]&&printf \[ printf \" e=${X[i]} e=${e//\\/\\\\} e=${e//\"/\\\"} for((j=0;j<${#e};j++));do c=${e:j:1} if [[ $c = [[:cntrl:]] ]];then printf '\\u%04x' "'$c" else printf %s "$c" fi done printf \" if((i<=${#X[@]}-2));then printf , else printf \] fi done
source to share
If you're ok with a few extra backslashes, bash is helpful printf "%q"
:
X=("hello world" "goodnight moon" 'say "boo"' 'foo\bar')
json="[$(printf '"%q",' "${X[@]}")"
json="${json%,}]"
echo "$json"
["hello\ world","goodnight\ moon","say\ \"boo\"","foo\\bar"]
Relatively OK for backslashes: node.js has no problem with them:
$ node
> x = ["hello\ world","goodnight\ moon","say\ \"boo\"","foo\\bar"]
[ 'hello world',
'goodnight moon',
'say "boo"',
'foo\\bar' ]
source to share