Python 3では、URLからjsonドキュメントをリクエストしています。
response = urllib.request.urlopen(request)
response
オブジェクトは、read
およびreadline
メソッドを持つファイルのようなオブジェクトです。通常、JSONオブジェクトは、テキストモードで開いたファイルで作成できます。
obj = json.load(fp)
私がやりたいことは:
obj = json.load(response)
ただし、urlopenはバイナリモードでファイルオブジェクトを返すため、これは機能しません。
回避策はもちろんです:
str_response = response.read().decode('utf-8')
obj = json.loads(str_response)
しかし、これは気分が悪い...
バイトファイルオブジェクトを文字列ファイルオブジェクトに変換するより良い方法はありますか?または、エンコードを与えるためのurlopen
またはjson.load
のパラメーターがありませんか?
HTTPはバイトを送信します。問題のリソースがテキストの場合、文字エンコーディングは通常、Content-Type HTTPヘッダーまたは別のメカニズム(RFC、HTML meta http-equiv
、...)によって指定されます。
urllib
shouldバイトを文字列にエンコードする方法を知っていますが、あまりにもナイーブです-それは恐ろしく力不足でPythonに基づかないライブラリです。
Dive Into Python は、状況に関する概要を提供します。
あなたの「回避策」は問題ありません。それは間違っていると感じますが、それを行う正しい方法です。
私は質問が最良の答えだと思うようになりました:)
import json
from urllib.request import urlopen
response = urlopen("site.com/api/foo/bar").read().decode('utf8')
obj = json.loads(response)
requests
ライブラリを使用してこれを解決しようとする他の人のために:
import json
import requests
r = requests.get('http://localhost/index.json')
r.raise_for_status()
# works for Python2 and Python3
json.loads(r.content.decode('utf-8'))
これは私のために働いています、私はjson()
で「リクエスト」ライブラリを使用しました 人間のリクエスト のドキュメントをチェックアウトしてください
import requests
url = 'here goes your url'
obj = requests.get(url).json()
Python 3.4.3&3.5.2およびDjango 1.11.3を使用して、同様の問題に遭遇しました。ただし、Python 3.6.1にアップグレードすると、問題はなくなりました。
詳細についてはこちらをご覧ください: https://docs.python.org/3/whatsnew/3.6.html#json
特定のバージョンのPythonに縛られていない場合は、3.6以降へのアップグレードを検討してください。
flaskマイクロフレームワークを使用しているときにこの問題が発生した場合は、次のようにします。
data = json.loads(response.get_data(as_text=True))
ドキュメントから :「as_textがTrueに設定されている場合、戻り値はデコードされたUnicode文字列になります」
あなたの回避策は実際に私を救った。 Falconフレームワークを使用してリクエストを処理する際に多くの問題が発生していました。これは私のために働いた。リクエストフォームcurl pr httpie
json.loads(req.stream.read().decode('utf-8'))
JSONとしてHttpResponseコンテンツを作成するためのこの簡単な方法を見つけました
import json
request = RequestFactory() # ignore this, this just like your request object
response = MyView.as_view()(request) # got response as HttpResponse object
response.render() # call this so we could call response.content after
json_response = json.loads(response.content.decode('utf-8'))
print(json_response) # {"your_json_key": "your json value"}
あなたに役立つことを願っています
これにより、バイトデータがJSONにストリーミングされます。
import io
obj = json.load(io.TextIOWrapper(response))
io.TextIOWrapperは、コーデックのモジュールリーダーよりも優先されます。 https://www.python.org/dev/peps/pep-0400/