Python Json加载()返回字符串而不是字典?
Posted
技术标签:
【中文标题】Python Json加载()返回字符串而不是字典?【英文标题】:Python Json loads() returning string instead of dictionary? 【发布时间】: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
。这就是我所期望的:结果对象是一个列表,而不是一个字符串。 >>> import json >>> json_string = json.dumps(output) >>> jason = json.loads(json_string) >>> print(jason['hashtags']) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: list indices must be integers, not str
这也甚至不是有效的 JSON,它只允许双引号字符串,不允许单引号字符串。
【参考方案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()
将返回您 dict。 string
--> json_dumps()
--> json_loads()
会返回字符串。你所给予的就是你所得到的。这是业力。【参考方案3】:
首先,您的 JSON 示例不是有效的 JSON; Twitter API 不会输出这个,因为它会破坏所有符合标准的 JSON 消费者。
jsonlint 显示了第一个明显的语法错误:单引号而不是双引号字符串。 其次,您有None
,其中 JSON 需要 null
、False
而不是 false
和 True
,而不是 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"])
【讨论】:
以上是关于Python Json加载()返回字符串而不是字典?的主要内容,如果未能解决你的问题,请参考以下文章
追加到 json 中转储的字典列表,而不用 python 加载列表
json.loads() 返回一个 unicode 对象而不是字典
对 Python 返回 JSON 作为字符串而不是文字感到困惑
如何在Python中将json.loads作为列表而不是字典[重复]
如何比较每个字典中 JSON Array 键值的字符串以查看它们是不是包含 NSUserDefault 字符串并返回 JSON 字典匹配项