【问题标题】:Python Json loads() returning string instead of dictionary?Python Json加载()返回字符串而不是字典?
【发布时间】:2014-10-26 03:19:49
【问题描述】:

我正在尝试使用 Python 3 的内置 JSON 模块进行一些简单的 JSON 解析,并且通过阅读有关 SO 和谷歌搜索的一堆其他问题,这似乎应该非常简单。但是,我认为我得到的是返回的字符串而不是预期的字典。

首先,这是我试图从中获取值的 JSON。这只是 Twitter API 的一些输出

[{'in_reply_to_status_id_str': None, 'in_reply_to_screen_name': None, 'retweeted':     False, 'in_reply_to_status_id': None, 'contributors': None, 'favorite_count': 0, 'in_reply_to_user_id': None, 'coordinates': None, 'source': '<a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>', 'geo': None, 'retweet_count': 0, 'text': 'Tweeting a url \nhttp://t.co/QDVYv6bV90', 'created_at': 'Mon Sep 01 19:36:25 +0000 2014', 'entities': {'symbols': [], 'user_mentions': [], 'urls': [{'expanded_url': 'http://www.isthereanappthat.com', 'display_url': 'isthereanappthat.com', 'url': 'http://t.co/QDVYv6bV90', 'indices': [16, 38]}], 'hashtags': []}, 'id_str': '506526005943865344', 'in_reply_to_user_id_str': None, 'truncated': False, 'favorited': False, 'lang': 'en', 'possibly_sensitive': False, 'id': 506526005943865344, 'user': {'profile_text_color': '333333', 'time_zone': None, 'entities': {'description': {'urls': []}}, 'url': None, 'profile_background_image_url': 'http://abs.twimg.com/images/themes/theme1/bg.png', 'profile_background_image_url_https': 'https://abs.twimg.com/images/themes/theme1/bg.png', 'protected': False, 'default_profile_image': True, 'utc_offset': None, 'default_profile': True, 'screen_name': 'KickzWatch', 'follow_request_sent': False, 'following': False, 'profile_background_color': 'C0DEED', 'notifications': False, 'description': '', 'profile_sidebar_border_color': 'C0DEED', 'geo_enabled': False, 'verified': False, 'friends_count': 40, 'created_at': 'Mon Sep 01 16:29:18 +0000 2014', 'is_translator': False, 'profile_sidebar_fill_color': 'DDEEF6', 'statuses_count': 4, 'location': '', 'id_str': '2784389341', 'followers_count': 4, 'favourites_count': 0, 'contributors_enabled': False, 'is_translation_enabled': False, 'lang': 'en', 'profile_image_url': 'http://abs.twimg.com/sticky/default_profile_images/default_profile_6_normal.png', 'profile_image_url_https': 'https://abs.twimg.com/sticky/default_profile_images/default_profile_6_normal.png', 'id': 2784389341, 'profile_use_background_image': True, 'listed_count': 0, 'profile_background_tile': False, 'name': 'Maktub Destiny', 'profile_link_color': '0084B4'}, 'place': None}]

我将此字符串分配给一个名为 json_string 的变量,如下所示:

json_string = json.dumps(output)
jason = json.loads(json_string)

然后,当我尝试从“jason”字典中获取特定键时:

print(jason['hashtags'])

我收到一个错误:

TypeError: string indices must be integers

我希望能够将 json 输出转换为字典,然后使用 jason[key_name] 调用使用指定键获取值。我在这里有什么明显的遗漏吗?

这是我从 Java 毕业后第一次使用 Python。我非常喜欢这种语言,并认为它非常强大。因此,我们将不胜感激任何帮助!

【问题讨论】:

  • 1) 您粘贴的数据是 Python 数据结构,而不是 JSON。 2) 外部数据结构是list,而不是字典。
  • @LukasGraf 嗯,很有趣。所以它是一个包含字典的列表?我只是注释掉了 json 逻辑,只是尝试了 output[0]['hashtags'] 没有运气。在这种情况下,“输出”是调用返回的 Python 数据结构。关于如何解决这个问题的任何想法?
  • 正如其他人指出的那样,您的 JSON 输入将在 Python 中变为 list ,而不是 dict 。此外,由于缺少右括号,您提供的代码 sn-p print(jason['hashtags'] 甚至不是有效的 Python。请发布一个语法正确的示例及其输出,以便我们确定是什么代码产生了什么错误。
  • 我得到一个不同的错误:TypeError: list indices must be integers, not str。这就是我所期望的:结果对象是一个列表,而不是一个字符串。 &gt;&gt;&gt; import json &gt;&gt;&gt; json_string = json.dumps(output) &gt;&gt;&gt; jason = json.loads(json_string) &gt;&gt;&gt; print(jason['hashtags']) Traceback (most recent call last): File "&lt;stdin&gt;", line 1, in &lt;module&gt; TypeError: list indices must be integers, not str
  • 甚至不是有效的 JSON,它只允许双引号字符串,不允许单引号字符串。

标签: python json parsing dictionary


【解决方案1】:

我做了 json.loads(json.loads(string)) 并且能够得到字典。你可以检查一下。第一次它不仅返回相同的字符串,而且处理它(例如删除 \ 字符。

【讨论】:

    【解决方案2】:

    好的,首先你应该打印你的对象以便你可以阅读它:

    >>> from pprint import pprint
    >>> output = [{'in_reply_to_status_id_str': None, 'in_reply_to_screen_name': None, 'retweeted':     False, 'in_reply_to_status_id': None, 'contributors': None, 'favorite_count': 0, 'in_reply_to_user_id': None, 'coordinates': None, 'source': '<a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>', 'geo': None, 'retweet_count': 0, 'text': 'Tweeting a url \nhttp://t.co/QDVYv6bV90', 'created_at': 'Mon Sep 01 19:36:25 +0000 2014', 'entities': {'symbols': [], 'user_mentions': [], 'urls': [{'expanded_url': 'http://www.isthereanappthat.com', 'display_url': 'isthereanappthat.com', 'url': 'http://t.co/QDVYv6bV90', 'indices': [16, 38]}], 'hashtags': []}, 'id_str': '506526005943865344', 'in_reply_to_user_id_str': None, 'truncated': False, 'favorited': False, 'lang': 'en', 'possibly_sensitive': False, 'id': 506526005943865344, 'user': {'profile_text_color': '333333', 'time_zone': None, 'entities': {'description': {'urls': []}}, 'url': None, 'profile_background_image_url': 'http://abs.twimg.com/images/themes/theme1/bg.png', 'profile_background_image_url_https': 'https://abs.twimg.com/images/themes/theme1/bg.png', 'protected': False, 'default_profile_image': True, 'utc_offset': None, 'default_profile': True, 'screen_name': 'KickzWatch', 'follow_request_sent': False, 'following': False, 'profile_background_color': 'C0DEED', 'notifications': False, 'description': '', 'profile_sidebar_border_color': 'C0DEED', 'geo_enabled': False, 'verified': False, 'friends_count': 40, 'created_at': 'Mon Sep 01 16:29:18 +0000 2014', 'is_translator': False, 'profile_sidebar_fill_color': 'DDEEF6', 'statuses_count': 4, 'location': '', 'id_str': '2784389341', 'followers_count': 4, 'favourites_count': 0, 'contributors_enabled': False, 'is_translation_enabled': False, 'lang': 'en', 'profile_image_url': 'http://abs.twimg.com/sticky/default_profile_images/default_profile_6_normal.png', 'profile_image_url_https': 'https://abs.twimg.com/sticky/default_profile_images/default_profile_6_normal.png', 'id': 2784389341, 'profile_use_background_image': True, 'listed_count': 0, 'profile_background_tile': False, 'name': 'Maktub Destiny', 'profile_link_color': '0084B4'}, 'place': None}]
    >>> pprint(output)
    [{'contributors': None,
      'coordinates': None,
      'created_at': 'Mon Sep 01 19:36:25 +0000 2014',
      'entities': {'hashtags': [],
                   'symbols': [],
                   'urls': [{'display_url': 'isthereanappthat.com',
                             'expanded_url': 'http://www.isthereanappthat.com',
                             'indices': [16, 38],
                             'url': 'http://t.co/QDVYv6bV90'}],
                   'user_mentions': []},
      'favorite_count': 0,
      'favorited': False,
      'geo': None,
      'id': 506526005943865344,
      'id_str': '506526005943865344',
      'in_reply_to_screen_name': None,
      'in_reply_to_status_id': None,
      'in_reply_to_status_id_str': None,
      'in_reply_to_user_id': None,
      'in_reply_to_user_id_str': None,
      'lang': 'en',
      'place': None,
      'possibly_sensitive': False,
      'retweet_count': 0,
      'retweeted': False,
      'source': '<a href="http://twitter.com" rel="nofollow">Twitter Web Client</a>',
      'text': 'Tweeting a url \nhttp://t.co/QDVYv6bV90',
      'truncated': False,
      'user': {'contributors_enabled': False,
               'created_at': 'Mon Sep 01 16:29:18 +0000 2014',
               'default_profile': True,
               'default_profile_image': True,
               'description': '',
               'entities': {'description': {'urls': []}},
               'favourites_count': 0,
               'follow_request_sent': False,
               'followers_count': 4,
               'following': False,
               'friends_count': 40,
               'geo_enabled': False,
               'id': 2784389341,
               'id_str': '2784389341',
               'is_translation_enabled': False,
               'is_translator': False,
               'lang': 'en',
               'listed_count': 0,
               'location': '',
               'name': 'Maktub Destiny',
               'notifications': False,
               'profile_background_color': 'C0DEED',
               'profile_background_image_url': 'http://abs.twimg.com/images/themes/theme1/bg.png',
               'profile_background_image_url_https': 'https://abs.twimg.com/images/themes/theme1/bg.png',
               'profile_background_tile': False,
               'profile_image_url': 'http://abs.twimg.com/sticky/default_profile_images/default_profile_6_normal.png',
               'profile_image_url_https': 'https://abs.twimg.com/sticky/default_profile_images/default_profile_6_normal.png',
               'profile_link_color': '0084B4',
               'profile_sidebar_border_color': 'C0DEED',
               'profile_sidebar_fill_color': 'DDEEF6',
               'profile_text_color': '333333',
               'profile_use_background_image': True,
               'protected': False,
               'screen_name': 'KickzWatch',
               'statuses_count': 4,
               'time_zone': None,
               'url': None,
               'utc_offset': None,
               'verified': False}}]
    

    从这里你可以看到输出是一个list,其中包含一个dict。要访问它,您需要:

    >>> first_elem = output[0]
    

    您还将看到first_elem 中的hashtags 键包含在entities 键下的第二级dict 中:

    >>> entities = first_elem['entities']
    >>> pprint(entities)
    {'hashtags': [],
     'symbols': [],
     'urls': [{'display_url': 'isthereanappthat.com',
               'expanded_url': 'http://www.isthereanappthat.com',
               'indices': [16, 38],
               'url': 'http://t.co/QDVYv6bV90'}],
     'user_mentions': []}
    

    现在您可以访问hashtags

    >>> entities['hashtags']
    []
    

    这恰好是一个空列表。

    要转换为 JSON,请注意注释:

    >>> import json
    >>> # Make sure output is the list object not a string representing the object
    >>> json_string = json.dumps(output)
    >>> jason = json.loads(output)
    >>> jason[0]['entities']['hashtags']
    []
    

    我认为您的问题是您在 json.dumps 之前输出了一个字符串,这意味着 json.loads 将返回一个字符串,而不是一个 json 对象。

    @Dan 的回答是正确的,这不是有效的 JSON。然而,它是一个有效的 python 字典,我假设你使用 python 从 Twitter 获取它然后打印它。

    【讨论】:

    • 他的问题在于他将已经是 Python 的结果编码回 JSON,然后再次返回 Python,然后遇到另一个不相关的问题 ;-)
    • 我将恢复对问题的编辑 - 如果问题保持其原始形式,您的回答会更有意义。
    • @Lukas ...好吧,如果您想获得技术...:P
    • 简而言之,dict --> json_dumps() --> json_loads() 将返回您 dictstring--> json_dumps() --> json_loads() 会返回字符串。你所给予的就是你所得到的。这是业力
    【解决方案3】:

    首先,您的 JSON 示例不是有效的 JSON; Twitter API 不会输出这个,因为它会破坏所有符合标准的 JSON 消费者。

    • jsonlint 显示了第一个明显的语法错误:单引号而不是双引号字符串。
    • 其次,您有 None,其中 JSON 需要 nullFalse 而不是 falseTrue,而不是 true

    您所谓的“JSON”示例似乎已被预解码为 Python :)。当我使用真实 JSON 的 sn-p 时,它的工作原理完全符合预期:

    import json
    
    json_string = r"""
    [{"actual_json_key":"actual_json_value"}]
    """
    
    jason = json.loads(json_string)
    
    print(jason[0]["actual_json_key"])
    

    【讨论】:

      猜你喜欢
      • 2020-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-19
      • 2019-08-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多