Error when trying to use urllib3 & json to get Rotten Tomatoes data (Python)

alanafrankly picture alanafrankly · Aug 7, 2014 · Viewed 7.5k times · Source

As an introduction to APIs, I'm trying to figure out how to access data in python using the Rotten Tomatoes API. This is also my first time dealing with json.

I'm using Python 3.4 and have confirmed that json and urllib3 have been installed.

Here is my code:

import urllib3
import json

url = 'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json?limit=16&country=us&apikey=API-KEY';

http = urllib3.PoolManager()
request = http.request('GET', url)
print (json.load(request));
request.release_conn()

Here is the error I get:

Traceback (most recent call last):
  File "C:\Users\admnasst1\Documents\Personal\Python\RotTomTest.py", line 16, in <module>
    print (str(json.load(request)));
  File "C:\Python34\lib\json\__init__.py", line 268, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File "C:\Python34\lib\json\__init__.py", line 312, in loads
    s.__class__.__name__))
TypeError: the JSON object must be str, not 'bytes'

Since I'm trying out so many new things (API, urllib3, json), I'm not exactly sure what's going on. I've tried doing a few other versions of the above code, and I keep getting the same error, so i think I must be missing something basic... Can any of you spot it?

Answer

Martijn Pieters picture Martijn Pieters · Aug 7, 2014

You'll need to decode the network data to a a string:

json.loads(request.data.decode('utf8'))

Ideally, you'd detect what codec was used from the Content-Type header; you'd parse that and look for a charset= parameter. The default encoding for JSON data is UTF-8.

If you are going to use a 3rd party library, use requests instead. It wraps urllib3 in a friendly API and can handle JSON for you:

import requests

url = 'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/box_office.json'
params = {'limit': 16, 'country': 'us', 'apikey': 'API-KEY'}

response = requests.get(url, params=params)
print(response.json())