I know there are tons of this exact question on here but I can't find an answer.
I'm trying to use the Google Maps API for Geocoding to go through a list of sloppy addresses, and get formatted addresses.
I have this exact code from the Google documentation:
import urllib2
address="1600+Amphitheatre+Parkway,+Mountain+View,+CA"
url="https://maps.googleapis.com/maps/api/geocode/json?address=%s" % address
response = urllib2.urlopen(url)
jsongeocode = response.read()
It then says that jsongeocode
is a JSON object. However, from what I've gathered from looking online is that this IS NOT a JSON object yet. If i'm wrong here and it is a JSON object, how do I parse it?
If I call print(jsongeocode)
it prints what appears to be a JSON object with the proper attributes in my terminal.
So I try to convert the jsongeocode
object to a JSON object:
jdata = json.load(jsongeocode)
This gives me this error:
AttributeError: 'bytes' object has no attribute 'read'
EDIT
I've switched the json function call to jdata = json.loads(jsongeocode)
, but now the error I get is this:
TypeError: The JSON Object must be str, not 'bytes'
Your code works fine in Python 2. You just need to parse the JSON string returned by the API using json.loads(jsongeocode)
.
The error message TypeError: The JSON Object must be str, not 'bytes'
suggests to me that you are using Python 3. However, you are importing the urllib2
module which is only present in Python 2. I'm not sure how you achieved that. Anyway, assuming Python 3:
import json
from urllib.request import urlopen
address="1600+Amphitheatre+Parkway,+Mountain+View,+CA"
url="https://maps.googleapis.com/maps/api/geocode/json?address=%s" % address
response = urlopen(url)
json_byte_string = response.read()
>>> type(json_byte_string)
<class 'bytes'>
>>> jdata = json.loads(json_byte_string)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python3.4/json/__init__.py", line 312, in loads
s.__class__.__name__))
TypeError: the JSON object must be str, not 'bytes'
So there is the exception that you have seen. The response contained in json_byte_string
is a byte string - it is of class bytes
, however, in Python 3 json.loads()
expects a str
which is a Unicode string. So you need to convert json_byte_string
from a byte string to Unicode. To do that requires that you know the encoding of the byte string. Here I use UTF8 because that is what was specified in the Content-Type
response header:
>>> response.headers['Content-Type']
'application/json; charset=UTF-8'
>>> json_string = str(json_byte_string, 'utf8')
>>> type(json_string)
<class 'str'>
Now it can be passed to json.loads()
:
>>> jdata = json.loads(json_string)
>>> jdata
{'results': [{'types': ['street_address'], 'address_components': [{'types': ['street_number'], 'long_name': '1600', 'short_name': '1600'}, {'types': ['route'], 'long_name': 'Amphitheatre Parkway', 'short_name': 'Amphitheatre Pkwy'}, {'types': ['locality', 'political'], 'long_name': 'Mountain View', 'short_name': 'Mountain View'}, {'types': ['administrative_area_level_2', 'political'], 'long_name': 'Santa Clara County', 'short_name': 'Santa Clara County'}, {'types': ['administrative_area_level_1', 'political'], 'long_name': 'California', 'short_name': 'CA'}, {'types': ['country', 'political'], 'long_name': 'United States', 'short_name': 'US'}, {'types': ['postal_code'], 'long_name': '94043', 'short_name': '94043'}], 'formatted_address': '1600 Amphitheatre Parkway, Mountain View, CA 94043, USA', 'geometry': {'location_type': 'ROOFTOP', 'viewport': {'northeast': {'lng': -122.0828811197085, 'lat': 37.4236854802915}, 'southwest': {'lng': -122.0855790802915, 'lat': 37.4209875197085}}, 'location': {'lng': -122.0842301, 'lat': 37.4223365}}, 'place_id': 'ChIJ2eUgeAK6j4ARbn5u_wAGqWA'}], 'status': 'OK'}
And there you have the decoded JSON string as a dictionary. The formatted address is available as:
>>> jdata['results'][0]['formatted_address']
'1600 Amphitheatre Parkway, Mountain View, CA 94043, USA'
There is a better way to do this: use requests
:
import requests
address="1600+Amphitheatre+Parkway,+Mountain+View,+CA"
url="https://maps.googleapis.com/maps/api/geocode/json?address=%s" % address
r = requests.get(url)
jdata = r.json()
>>> jdata['results'][0]['formatted_address']
'1600 Amphitheatre Parkway, Mountain View, CA 94043, USA'
Much better!