How to parse json response in the shell script?

10,841

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.

Share:
10,841
john
Author by

john

Updated on July 31, 2022

Comments

  • john
    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
    john almost 10 years
    Thanks 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
    john almost 10 years
    nopes, I mean to say, if the key is success, echo $DATA; exit 0 and if key is error, then echo $DATA; exit 2. Something like this?
  • john
    john almost 10 years
    sorry I was away for a while. I have updated the question. can you see whether I got everything correctly in my shell script?
  • konsolebox
    konsolebox almost 10 years
    Yes it seems correct enough. Just one thing. You should quote $DATA to be safe from pathname expansion: echo "$DATA"
  • konsolebox
    konsolebox almost 10 years
    There'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 do exit 2 for any other that's not success nor error. If so you can add *) exit 2 ;;. On the other hand if you just want to exit with 0 for success, and 1 for anything besides it, just consider the last part of my answer. It's simple enough.