Python JSON loads () возвращает строку вместо словаря?

Я пытаюсь сделать простой синтаксический анализ JSON, используя встроенный модуль JSON Python 3, и из чтения куча других вопросов на SO и googling, кажется, это должно быть довольно просто. Тем не менее, я думаю, что получаю строку, возвращенную вместо ожидаемого словаря.

во-первых, вот JSON, из которого я пытаюсь получить значения. Это просто некоторые выходные данные из API Twitter

[{'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] вызов для получения значений с помощью указанных ключей. Есть что-то очевидное, что я упускаю?

Это мое первое время работы с Python, после выхода из Java. Я очень люблю этот язык и считаю его очень мощным. Итак, любая помощь в этом будет очень признательна!

2 ответов


Ok сначала вы должны напечатать свой объект, чтобы вы могли его прочитать:

>>> 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]

вы также увидите, что hashtags ключ в first_elem содержится на втором уровне dict под ключ entities:

>>> 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 dict, и я предполагаю, что вы получили его из Twitter с помощью python, а затем напечатали его.


во-первых, ваш пример JSON недействителен JSON; API Twitter не будет выводить это, потому что это сломает каждого соответствующего потребителя JSON.

  • jsonlint показывает первую очевидную синтаксическую ошибку: одинарные, а не двойные кавычки строк.
  • во-вторых, у вас есть None где JSON требует null, False вместо false и True, вместо true.

ваш предполагаемый пример "JSON" появляется быть предварительно декодированным в Python :). Когда я использую фрагмент реального JSON, он работает точно так, как ожидалось:

import json

json_string = r"""
[{"actual_json_key":"actual_json_value"}]
"""

jason = json.loads(json_string)

print(jason[0]["actual_json_key"])