2015-06-19 5 views
1

Я знаю, что здесь есть тонны этого точного вопроса, но я не могу найти ответ.Как разобрать объект JSON в Python

Я пытаюсь использовать Google Maps API for Geocoding, чтобы просмотреть список неактивных адресов и получить отформатированные адреса.

У меня есть этот точный код из документации Google:

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' 

EDIT

Я переключил JSON вызов функции jdata = json.loads(jsongeocode), но теперь я получаю следующее сообщение:

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

ответ

2

Ваш код отлично работает в Python 2. Вам просто нужно разобрать строку JSON, возвращаемый API с использованием json.loads(jsongeocode).

Сообщение об ошибке TypeError: The JSON Object must be str, not 'bytes' подсказывает мне, что вы используете Python 3. Однако вы импортируете модуль urllib2, который присутствует только в Python 2. Я не уверен, как вы это достигли. В любом случае, если предположить, что 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 
Смежные вопросы