2015-06-19 92 views
1

我知道這裏有很多精確的問題,但我找不到答案。如何在Python中通過JSON對象進行解析

我試圖使用Google Maps API for Geocoding來查看一個粗糙的地址列表,並獲得格式化的地址。

我已經從谷歌文檔,這個確切的代碼:

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() 

然後它說jsongeocode是一個JSON對象。但是,從我在網上收集的信息來看,這不是一個JSON對象。 如果我在這裏錯了,它是一個JSON對象,我該如何解析它?

如果我打電話print(jsongeocode)它打印看起來是JSON對象與我的終端中的正確屬性。

所以我嘗試了jsongeocode對象轉換爲一個JSON對象:

jdata = json.load(jsongeocode) 

這給了我這個錯誤:

AttributeError: 'bytes' object has no attribute 'read' 

編輯

我切換了JSON函數調用jdata = json.loads(jsongeocode),但現在我得到的錯誤是這樣的:

TypeError: The JSON Object must be str, not 'bytes' 

回答

2

您的代碼在Python 2中正常工作。您只需要使用json.loads(jsongeocode)解析由API返回的JSON字符串。

錯誤消息TypeError: The JSON Object must be str, not 'bytes'向我建議您使用Python 3.但是,您正在導入僅在Python 2中存在的urllib2模塊。我不確定您是如何實現這一點的。無論如何,假設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' 

所以你有看到的例外。包含在json_byte_string中的響應是一個字節字符串 - 它屬於bytes類,但是,在Python 3中,json.loads()需要str這是一個Unicode字符串。因此,您需要將json_byte_string從字節字符串轉換爲Unicode。要做到這一點,需要知道字節字符串的編碼。這裏我用UTF8,因爲那是什麼在Content-Type響應頭規定:

>>> response.headers['Content-Type'] 
'application/json; charset=UTF-8' 

>>> json_string = str(json_byte_string, 'utf8') 
>>> type(json_string) 
<class 'str'> 

現在,它可以傳遞給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'} 

有你有解碼JSON字符串作爲字典。該格式的地址可作爲:

>>> jdata['results'][0]['formatted_address'] 
'1600 Amphitheatre Parkway, Mountain View, CA 94043, USA' 

有一個更好的方式來做到這一點:使用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' 

好多了!

-2

使用

jsongeocode = str(response.read()) 
jdata = json.loads(jsongeocode) 

json.load()是類文件對象,如下所述: https://docs.python.org/2/library/json.html#json.load

+0

仍然無法正常工作。我認爲'json.loads()'是正確的函數調用,但我得到相同的錯誤。 – JuiCe

+0

我拿回去!這是一個不同的錯誤。我會更新我的問題 – JuiCe

+0

是的,你需要轉換成一個字符串之前,請參閱更新。 – Geotob

-2
this is my jsongeocode: 

{ 
    "results" : [ 
     { 
     "address_components" : [ 
      { 
       "long_name" : "1600", 
       "short_name" : "1600", 
       "types" : [ "street_number" ] 
      }, 
      { 
       "long_name" : "Amphitheatre Parkway", 
       "short_name" : "Amphitheatre Pkwy", 
       "types" : [ "route" ] 
      }, 
      { 
       "long_name" : "Mountain View", 
       "short_name" : "Mountain View", 
       "types" : [ "locality", "political" ] 
      }, 
      { 
       "long_name" : "Santa Clara County", 
       "short_name" : "Santa Clara County", 
       "types" : [ "administrative_area_level_2", "political" ] 
      }, 
      { 
       "long_name" : "California", 
       "short_name" : "CA", 
       "types" : [ "administrative_area_level_1", "political" ] 
      }, 
      { 
       "long_name" : "United States", 
       "short_name" : "US", 
       "types" : [ "country", "political" ] 
      }, 
      { 
       "long_name" : "94043", 
       "short_name" : "94043", 
       "types" : [ "postal_code" ] 
      } 
     ], 
     "formatted_address" : "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA", 
     "geometry" : { 
      "location" : { 
       "lat" : 37.4223365, 
       "lng" : -122.0842301 
      }, 
      "location_type" : "ROOFTOP", 
      "viewport" : { 
       "northeast" : { 
        "lat" : 37.4236854802915, 
        "lng" : -122.0828811197085 
       }, 
       "southwest" : { 
        "lat" : 37.4209875197085, 
        "lng" : -122.0855790802915 
       } 
      } 
     }, 
     "place_id" : "ChIJ2eUgeAK6j4ARbn5u_wAGqWA", 
     "types" : [ "street_address" ] 
     } 
    ], 
    "status" : "OK" 
} 

你可以找到的差異

的方式: 你可以發送http請求使用請求模塊:

import requests 

address="1600+Amphitheatre+Parkway,+Mountain+View,+CA" 
url="https://maps.googleapis.com/maps/api/geocode/json?address=%s" % address 

response = requests.get(url) 
jsongeocode = response.text