1

I'm trying to use an API with curl, returning a JSON:

response=$(curl -i --user api:$APIKey --data-binary @$target https://api.tinypng.com/shrink)

Next, I try to parse (briefly) the response with a function:

parseJson(){
    result="$1"
    result=($(echo $result | python -mjson.tool))
    result=${result%\"*}
    result=${result##*\"}
    return $result
}

and I'm calling it like this: message=$(parseJson "$response" message). FYI, the response is on multiple lines.

But weird thing happened: python gave me No JSON object could be decoded, but if I echoed $result there is a good JSON string. Weirder, if I echoed it before calling python, it looks like python is executed first anyway.

Is there some asynchronous trick ? Why can't I pass my variable string to python ?

Any help or better method will be greatly appreciated!

NorTicUs
  • 718
  • 1
  • 10
  • 27
  • are you sure that the string you receive is an actual json string? Did you check it for instance on http://jsonformatter.curiousconcept.com/ ? – ezdazuzena Dec 03 '13 at 15:59
  • I tested it in a terminal, worked great. Even tested it without the bash function, worked too. That's why I wondered if passing it as an argument could affect it somehow – NorTicUs Dec 03 '13 at 16:10

2 Answers2

2

No JSON Object could be decoded and the response is on multiple lines are the keys here I think. That error is usually returned from mjson.tools on an empty string, whereas malformed JSON generally returns something more verbose.

The JSON parser will not look past the first newline (outside of a quote string value). It is probably receiving something like \r\n{"key":"value"} and failing. If the response is on multiple lines for some reason, then you should parse out the response body (JSON) without leading or trailing \r\n's

Evan Cordeiro
  • 773
  • 10
  • 12
  • You were right, my echoes didn't show me there was lines before my JSON (HTTP header mostly). When I strip those whith `tail` it works perfectly! – NorTicUs Dec 03 '13 at 16:38
1

You can try HttpConnection instead of calling curl and do everything directly in python:

conn = httplib.HTTPConnection('www.a_url.com')
conn.request("GET", /index.html')
response = conn.getresponse()
status = response.status
if status != 200:
    print 'ERROR'
    sys.exit(1)
reason = response.reason
answer = response.read()

in order to get the json just do:

received_json = None
try:
    json.loads(answer)
except:
    print 'ERROR'
    sys.exit(2)
ezdazuzena
  • 6,120
  • 6
  • 41
  • 71
  • I'm not very familiar with Python, so how am I supposed to set my curl paramaters (--user & --data-binary) to my HTTPConnection? Thanks – NorTicUs Dec 03 '13 at 16:08
  • That might be a different question. But have a look for example at http://stackoverflow.com/q/34079/1141095 though it's not HttpConnection, the same should work in my example – ezdazuzena Dec 03 '13 at 16:19