How to parse json response in the shell script?
Solution 1
#!/bin/bash
IFS= read -d '' DATA < temp.txt ## Imitates your DATA=$(wget ...). Just replace it.
while IFS=\" read -ra LINE; do
case "${LINE[1]}" in
error)
# ERROR_MSG=${LINE[3]}
printf -v ERROR_MSG '%b' "${LINE[3]}"
;;
success)
# SUCCESS_MSG=${LINE[3]}
printf -v SUCCESS_MSG '%b' "${LINE[3]}"
;;
esac
done <<< "$DATA"
echo "$ERROR_MSG|$SUCCESS_MSG" ## Shows: error_message|success_message
* %b
expands backslash escape sequences in the corresponding argument.
Update as I didn't really get the question at first. It should simply be:
IFS=\" read __ KEY __ MESSAGE __ <<< "$DATA"
[[ $KEY == success ]] ## Gives $? = 0 if true or else 1 if false.
And you can examine it further:
case "$KEY" in
success)
echo "Success message: $MESSAGE"
exit 0
;;
error)
echo "Error message: $MESSAGE"
exit 1
;;
esac
Of course similar obvious tests can be done with it:
if [[ $KEY == success ]]; then
echo "It was successful."
else
echo "It wasn't."
fi
From your last comment it can be simply done as
IFS=\" read __ KEY __ MESSAGE __ <<< "$DATA"
echo "$DATA" ## Your really need to show $DATA and not $MESSAGE right?
[[ $KEY == success ]]
exit ## Exits with code based from current $?. Not necessary if you're on the last line of the script.
Solution 2
If you are going to be using any more complicated json from the shell and you can install additional software, jq is going to be your friend.
So, for example, if you want to just extract the error message if present, then you can do this:
$ echo '{"error": "Some Error"}' | jq ".error"
"Some Error"
If you try this on the success case, it will do:
$echo '{"success": "Yay"}' | jq ".error"
null
The main advantage of the tool is simply that it fully understands json. So, no need for concern over corner cases and whatnot.
john
Updated on July 31, 2022Comments
-
john almost 2 years
I am working with bash shell script. I need to execute an URL using shell script and then parse the json data coming from it.
This is my URL -
http://localhost:8080/test_beat
and the responses I can get after hitting the URL will be from either these two -{"error": "error_message"} {"success": "success_message"}
Below is my shell script which executes the URL using wget.
#!/bin/bash DATA=$(wget -O - -q -t 1 http://localhost:8080/test_beat) #grep $DATA for error and success key
Now I am not sure how to parse json response in $DATA and see whether the key is success or error. If the key is success, then I will print a message "success" and print $DATA value and exit out of the shell script with zero status code but if the key is error, then I will print "error" and print $DATA value and exit out of the shell script with non zero status code.
How can I parse json response and extract the key from it in shell script?
I don't want to install any library to do this since my JSON response is fixed and it will always be same as shown above so any simpler way is fine.
Update:-
Below is my final shell script -
#!/bin/bash DATA=$(wget -O - -q -t 1 http://localhost:8080/tester) echo $DATA #grep $DATA for error and success key IFS=\" read __ KEY __ MESSAGE __ <<< "$DATA" case "$KEY" in success) exit 0 ;; error) exit 1 ;; esac
Does this looks right?
-
john almost 10 yearsThanks konsolebox but I also need to have exit status code. If the key is success, then exit status code should be 0 but if it is error, then exit status code should be non zero. How would I do that as well?
-
john almost 10 yearsnopes, I mean to say, if the key is success,
echo $DATA; exit 0
and if key is error, thenecho $DATA; exit 2
. Something like this? -
john almost 10 yearssorry I was away for a while. I have updated the question. can you see whether I got everything correctly in my shell script?
-
konsolebox almost 10 yearsYes it seems correct enough. Just one thing. You should quote $DATA to be safe from pathname expansion:
echo "$DATA"
-
konsolebox almost 10 yearsThere's another: What would you want the return value if no data was caught? e.g. Download errors, invalid data, etc. Do you want to
exit 1
for anything besides success? Or perhaps doexit 2
for any other that's notsuccess
norerror
. If so you can add*) exit 2 ;;
. On the other hand if you just want to exit with0
for success, and1
for anything besides it, just consider the last part of my answer. It's simple enough.