Рядок до словника в Python


126

Тому я витратив багато часу на це, і мені здається, що це повинно бути простим виправленням. Я намагаюся використовувати автентифікацію Facebook для реєстрації користувачів на моєму сайті, і я намагаюся це зробити на сервері. Я дійшов до моменту, коли я отримую свій маркер доступу, і коли переходжу до:

https://graph.facebook.com/me?access_token=MY_ACCESS_TOKEN

Я отримую інформацію, яку я шукаю, як рядок, такий:

{"id":"123456789","name":"John Doe","first_name":"John","last_name":"Doe","link":"http:\/\/www.facebook.com\/jdoe","gender":"male","email":"jdoe\u0040gmail.com","timezone":-7,"locale":"en_US","verified":true,"updated_time":"2011-01-12T02:43:35+0000"}

Здається, я повинен просто використовувати dict(string)це, але я отримую цю помилку:

ValueError: dictionary update sequence element #0 has length 1; 2 is required

Тому я спробував використовувати Pickle, але отримав цю помилку:

KeyError: '{'

Я намагався використовувати його django.serializersдля десериалізації, але мав подібні результати. Будь-які думки? Я відчуваю, що відповідь повинна бути простою, і я просто дурний. Дякуємо за будь-яку допомогу!


Якщо ви хочете оцінити рядок як Python, можливо, вам знадобиться змінити рядок: "verified":trueне вдається, якщо trueне визначено. Або ви могли використовувати "verified":True, або "verified":"true".
Метт Кертіс

2
@Matt: я сумніваюся, що він може змінити вихідний формат graph.facebook.com.
Фред Нурк

@Fred: Враховуючи назву питання ("Рядок до словника на Python"), я думаю, він міг би змінити його з Python, перш ніж він дзвонить ast.literal_eval(). Ваша (переглянута) відповідь правильна, хоча - десеріалізатор JSON - це краще рішення.
Метт Кертіс

1
@MattCurtis: Для зміни цього в надійному порядку (до ast.literal_eval) в першу чергу потрібно буде розібрати його як JSON. Я згадував ast.literal_eval як вірний спосіб зробити те, що ОП намагався зробити з dict (some_string).
Фред Нурк

@Fred: Я думаю, ми погоджуємось погодитись :-)
Метт Кертіс

Відповіді:


239

Це дані JSON ! Ви можете десаріалізувати його за допомогою вбудованого jsonмодуля, якщо ви перебуваєте на Python 2.6+, інакше ви можете використовувати відмінний сторонній simplejsonмодуль .

import json    # or `import simplejson as json` if on Python < 2.6

json_string = u'{ "id":"123456789", ... }'
obj = json.loads(json_string)    # obj now contains a dict of the data

5
Чому ви поставили uперед своїм прикладом рядок JSON?
Джон Махін

2
@John: Це вказує рядок Unicode . Я викладаю це здебільшого просто за звичкою, але, імовірно, API Facebook може повертати дані з символами, що не містять ASCII; у такому випадку дані будуть закодовані (ймовірно, в UTF-8), і decode()-ing це дасть unicodeрядок - що я використовував у своєму прикладі. Також ця сторінка згадує, що JSON завжди знаходиться в Unicode (шукайте термін, це приблизно на півдорозі)
Камерон

3
Він вказує на малий літер-унікод-u у Python. Звичка - не вагома причина. "Кодування символів тексту JSON завжди є Unicode." - Нікод [Uu] НЕ кодує. Що json.loads () очікує - це те, що ви отримали "по дроту", що, як правило, є об'єктом str, закодованим в ASCII. Єдиний випадок, коли ви навмисно будете подавати json.loads () об’єкт unicode - це те, коли якась дивна людина передавала його в UTF-16, і як це документально підтверджено, вам потрібно розшифрувати його самостійно.
Джон Махін

1
@John: Так, small-u unicode- тип Python, який містить рядок Unicode (big-U власний іменник). Я також погоджуюся, що Unicode - це зовсім не кодування, тому, можливо, я не повинен вказувати на цю сторінку як посилання. Немає ніяких причин уникати передачі unicodeрядків json.loads, хоча - документи чітко стверджують, що це цілком прийнятно, і мені подобається використовувати попередньо розшифровану рядок, оскільки вона більш чітка.
Камерон

8
@John: Вибачте за педантичний, але json.loads()не чекає strоб'єкта, закодованого в ASCII - він очікує або strоб'єкт, закодований в UTF-8, або unicodeоб'єкт (або strоб'єкт плюс явне кодування)
Cameron

19

Використовуйте ast.literal_eval для оцінки літералів Python. Однак у вас є JSON (примітка "вірне" наприклад), тому використовуйте десеріалізатор JSON.

>>> import json
>>> s = """{"id":"123456789","name":"John Doe","first_name":"John","last_name":"Doe","link":"http:\/\/www.facebook.com\/jdoe","gender":"male","email":"jdoe\u0040gmail.com","timezone":-7,"locale":"en_US","verified":true,"updated_time":"2011-01-12T02:43:35+0000"}"""
>>> json.loads(s)
{u'first_name': u'John', u'last_name': u'Doe', u'verified': True, u'name': u'John Doe', u'locale': u'en_US', u'gender': u'male', u'email': u'jdoe@gmail.com', u'link': u'http://www.facebook.com/jdoe', u'timezone': -7, u'updated_time': u'2011-01-12T02:43:35+0000', u'id': u'123456789'}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.