My BASH function:
json_format () {
echo '{
"question": "';echo "$1";echo '",'
}
for:
json_format ${questions[$Q_counter]}
Is returning:
{
"question": "
VM
",
Instead of expected json format and string:
{
"question": "VM CPU is at 100% and you'r jumpbox creds be broken! What do you do?",
The string appears to be cut off at the space after the first word "VM", and the formatting is a little off with those echo commands. How can i correct my function? Thanks!
The ideal way to generate JSON from shell is to use a tool such as jq
that actually understands the format:
json_format() {
jq -n --arg q "$1" '{"question": $q}'
}
...or, if you have a Python interpreter, the built-in json
module can also be used:
json_format() {
python -c 'import sys, json; print json.dumps({"question": sys.argv[1]})' "$1"
}
If you don't have any of those tools, however, at least make a best-effort attempt at escaping:
json_format() {
local s=$1
s=${s//'\'/'\\'} # replace \ with \\
s=${s//'"'/'\"'} # replace " with \"
s=${s//$'\n'/'\n'} # replace newline literals with \n
printf '{\n\t"question": "%s"\n}\n' "$s"
}
...or, to process one value at a time:
json_format() {
local s=$1
s=${s//'\'/'\\'} # replace \ with \\
s=${s//'"'/'\"'} # replace " with \"
s=${s//$'\n'/'\n'} # replace newline literals with \n
printf '%s\n' "$s"
}
...invoked individually for each string to be formatted, as in:
cat <<EOF
{
"question": "$(json_format "$question")",
"image": "$(json_format "$image_url")",
"choices": [ ],
"correct": [ "$(json_format "$answer")" ],
"explanation": "$(json_format "$explanation")"
}
EOF
This will work correctly with cases for which naive approaches will produce valid that is not in fact valid JSON. Consider, for instance:
# naive string substitution will fail here because it won't escape double quotes
json_format 'How do you spell "hello" in Spanish?'
or
# naive string substitution will fail here because it won't escape the newline
json_format $'This question has\ntwo lines'
or
# naive string substitution will fail here because it won't escape the backslash
json_format 'This question ends in a backslash: \'
Note, in all of the above, the quoting -- which ensures that the string is passed as a single argument.