4

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?

5 Answers 5

5

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.

Sign up to request clarification or add additional context in comments.

Comments

2
#!/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.

5 Comments

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?
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?
sorry I was away for a while. I have updated the question. can you see whether I got everything correctly in my shell script?
Yes it seems correct enough. Just one thing. You should quote $DATA to be safe from pathname expansion: echo "$DATA"
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.
1

Pure Bash 3.2+ without dependencies (such as jq, python, grep, etc.):

source <(curl -s -L -o- https://github.com/lirik90/bashJsonParser/raw/master/jsonParser.sh)
JSON='{"error": "error_message"}'
JSON=$(minifyJson "$JSON")
echo "Message is: $(parseJson "$JSON" error)"

Try it.

Comments

0

You probably already have python installed, which has json parsing in the standard library. Python is not a great language for one-liners in shell scripts, but here is one way to use it:

#!/bin/bash

DATA=$(wget -O - -q -t 1 http://localhost:8080/test_beat)

if python -c '
import json, sys
exit(1 if "error" in json.loads(sys.stdin.read()) else 0)' <<<"$DATA"
then
  echo "SUCCESS: $DATA"
else
  echo "ERROR: $DATA"
  exit 1
fi

Comments

0

Given:

  • that you don't want to use JSON libraries.
  • and that the response you're parsing is simple and the only thing you care about is the presence of substring "success", I suggest the following simplification:
#!/bin/bash

wget -O - -q -t 1 http://localhost:8080/tester | grep -F -q '"success"'
exit $?
  • -F tells grep to search for a fixed (literal) string.
  • -q tells grep to produce no output and instead only reflect via its exit code whether a match was found or not.
  • exit $? simply exits with grep's exit code ($? is a special variable that reflects the most recently executed command's exit code).

Note that if you all you care about is whether wget's output contains "success", the above pipeline will do - no need to capture wget's output in an aux. variable.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.