Строка в словарь в 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для десериализации, но получил аналогичные результаты. Есть предположения? Я чувствую, что ответ должен быть простым, а я просто дурак. Спасибо за любую помощь!

LunaCodeGirl
источник
Если вы хотите оценить строку как Python, вам может потребоваться изменить строку: "verified":truefails, если 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 как правильный способ сделать то, что OP пытался сделать с 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
Cameron
источник
5
Почему вы поместили uперед своим примером строку JSON?
Джон Мачин
2
@John: указывает строку Unicode . Я использовал это в основном просто по привычке, но, по-видимому, API Facebook может возвращать данные с не-ASCII символами в нем; в этом случае данные будут закодированы (возможно, в UTF-8), и в результате decode()получится unicodeстрока - это то, что я использовал в моем примере. Кроме того, на этой странице упоминается, что JSON всегда находится в Юникоде (ищите термин, он примерно на полпути вниз)
Кэмерон
3
Он указывает на юникод-литерал маленького u в Python. Привычка - не повод. «Кодировка символов текста JSON всегда Unicode». - [Uu] nicode НЕ является кодировкой. То, что ожидает 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объект плюс явное кодирование)
Кэмерон
19

Используйте ast.literal_eval для оценки литералов Python. Однако у вас есть JSON (например, обратите внимание на «true»), поэтому используйте десериализатор 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'}
Фред Нурк
источник