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

だから私はピクルスを使ってみましたが、このエラーが発生しました:

KeyError: '{'

を使用django.serializersしてシリアル化を解除しましたが、同様の結果が得られました。何かご意見は?答えは単純でなければならないような気がします、そして私はただ愚かです。助けてくれてありがとう!


文字列をPythonとして評価する場合は、文字列を変更する必要がある場合があります。が定義されてい"verified":trueない場合trueは失敗します。または"verified":True、またはを使用できます"verified":"true"
Matt Curtis、

2
@マット:彼がgraph.facebook.comの出力フォーマットを変更できるとは思えません。
Fred Nurk、2011

@フレッド:質問のタイトル(「Pythonの文字列から辞書へ」)を考えると、彼がを呼び出す前に、Pythonから変更できると思いますast.literal_eval()。あなたの(修正された)答えは正しいですが、JSONデシリアライザの方が優れたソリューションです。
Matt Curtis、

1
@MattCurtis:堅牢な方法(ast.literal_evalの前)で変更するには、そもそもJSONとして解析する必要があります。OPがdict(some_string)で実行しようとしたことを実行する正しい方法として、ast.literal_evalについて言及しました。
Fred Nurk、2011

@フレッド:私たちは同意することに同意していると思います:-)
Matt Curtis

回答:


238

このデータは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

5
なぜuJSON文字列の例の前に置いたのですか?
John Machin、2011

2
@John:Unicode文字列を示します。私はそれを習慣から外しただけですが、おそらくFacebook APIは非ASCII文字を含むデータを返すことができます。その場合、データは(おそらくUTF-8で)エンコードされ、decode()-ingするとunicode文字列が生成されます-これが私の例で使用したものです。また、このページでは、JSONが常にUnicodeであると述べています(用語を検索すると、半分ほど下にあります)
Cameron、

3
Pythonのsmall-uユニコードリテラルを示します。習慣は正当な理由ではありません。「JSONテキストの文字エンコードは常にUnicodeです。」-[Uu] nicodeはエンコーディングではありません。json.loads()が期待するのは、通常、ASCIIでエンコードされたstrオブジェクトである「ネットワーク経由」で取得したものです。json.loads()に意図的にUnicodeオブジェクトをフィードする唯一のケースは、奇妙な人物がそれをUTF-16で送信し、文書化されているように自分でデコードする必要がある場合です。
John Machin、2011

1
@John:はい、small-u unicodeはPython型で、Unicode(big-U固有名詞)文字列が含まれています。また、Unicodeはエンコーディングではないことにも同意します。そのため、そのページを参照として指定するべきではありません。ただし、unicode文字列をjson.loadsに渡さないようにする理由はありません。ドキュメントには、これが完全に受け入れ可能であると明確に記載されており、プリデコードされた文字列をより明示的に使用することを好みます。
Cameron

8
@John:申し訳ありませんが、ASCIIでエンコードされjson.loads()strオブジェクトを想定していません-UTF -8でstrエンコードされたオブジェクトまたはオブジェクト(またはオブジェクトと明示的なエンコード)のどちらかを想定していますunicodestr
Cameron

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'}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.