【问题标题】:How to parse through JSON object in Python如何在 Python 中解析 JSON 对象
【发布时间】:2015-06-19 02:51:57
【问题描述】:

我知道这里有很多确切的问题,但我找不到答案。

我正在尝试使用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'

编辑

我已将 json 函数调用切换为 jdata = json.loads(jsongeocode),但现在我得到的错误是:

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

【问题讨论】:

    标签: python json google-geocoding-api


    【解决方案1】:

    您的代码在 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

      【讨论】:

      • 还是不行。我认为json.loads() 是正确的函数调用,但我得到了同样的错误。
      • 我收回了!这是一个不同的错误。我会更新我的问题
      • 是的,您需要先转换为字符串,请参阅更新。
      • 谢谢,现在似乎可以正确调用了。但是,它现在给了我AttributeError: Expecting Value: line 1 column 1 (char 0)。我现在正在调查。
      【解决方案3】:
      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"
      }
      

      你会发现区别

      顺便说一句: 你可以像这样使用 Requests 模块发送 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
      

      【讨论】:

        猜你喜欢
        • 2021-03-19
        • 2011-07-30
        • 2015-05-18
        • 2013-04-06
        • 2017-09-03
        • 2016-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多