Python中的字符串转字典

182

我在这上面花费了太多时间,但似乎这应该是一个简单的修复。我正在尝试使用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" - Matt Curtis
2
@Matt:我怀疑他无法更改graph.facebook.com的输出格式。 - Fred Nurk
@Fred:根据问题的标题(“Python中的字符串转字典”),我猜他在调用ast.literal_eval()之前可以从Python中进行更改。尽管如此,您(修订后)的答案是正确的 - JSON反序列化程序是更好的解决方案。 - Matt Curtis
1
@MattCurtis:以强大的方式更改它(在ast.literal_eval之前)需要首先将其解析为JSON。我提到ast.literal_eval是执行OP尝试使用dict(some_string)完成操作的正确方法。 - Fred Nurk
相关:https://dev59.com/OnNA5IYBdhLWcg3wX8rk(虽然这里可以使用JSON,但不是重复问题) - Tobias Kienzler
显示剩余2条评论
3个回答

334

这份数据是JSON格式的!如果你使用的是Python 2.6+版本,你可以使用内置的json模块来完成反序列化操作;否则,你可以使用优秀的第三方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

9
你为什么在示例 JSON 字符串前面加了 u - John Machin
2
@John: 它表示一个[Unicode字符串](http://docs.python.org/howto/unicode.html#the-unicode-type)。我之所以大多数时候都这样做,主要是出于习惯,但据推测,Facebook API可以返回包含非ASCII字符的数据;在这种情况下,数据将被编码(可能以UTF-8为例),并且解码后会产生Unicode字符串-这就是我在示例中使用的内容。此外,[此页面](http://www.json.org/fatfree.html)提到JSON始终以Unicode方式呈现(搜索该术语,它在页面中部)。 - Cameron
3
这段话是关于Python中的小写U Unicode字面量以及JSON文本编码的说明。它强调了习惯不是一个好的理由。JSON文本的字符编码总是Unicode,但是[Uu]nicode不是一种编码方式。json.loads()函数期望从“over the wire”中获取的通常是ASCII编码的str对象。唯一会故意向json.loads()提供Unicode对象的情况是当某些奇怪的人以UTF-16传输时,你需要按照文档的规定自己进行解码。 - John Machin
1
@John:是的,small-u unicode 是Python类型,其中包含Unicode(大写U专有名词)字符串。我也同意Unicode根本不是编码,所以也许我不应该将那个页面作为参考。然而,并没有理由避免向json.loads传递unicode字符串--文档明确说明这是完全可接受的,而且我喜欢使用预解码的字符串,因为它更加明确。 - Cameron
10
抱歉我要苛刻一些,但是json.loads()不接受用ASCII编码的str对象--它需要一个使用UTF-8编码的str对象,或者一个unicode对象(或者一个带有显式编码的str对象)。 - Cameron

24
使用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'}

1
在Python 3.x中
import json
t_string = '{"Prajot" : 1, "Kuvalekar" : 3}'
res = json.loads(t_string)
print(res) # <dict>  {"Prajot" : 1, "Kuvalekar" : 3}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接