web-dev-qa-db-ja.com

JSONオブジェクトにバイトを許可させるか、urlopenに文字列を出力させます

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のパラメーターがありませんか?

175
Peter Smit

HTTPはバイトを送信します。問題のリソースがテキストの場合、文字エンコーディングは通常、Content-Type HTTPヘッダーまたは別のメカニズム(RFC、HTML meta http-equiv、...)によって指定されます。

urllibshouldバイトを文字列にエンコードする方法を知っていますが、あまりにもナイーブです-それは恐ろしく力不足でPythonに基づかないライブラリです。

Dive Into Python は、状況に関する概要を提供します。

あなたの「回避策」は問題ありません。それは間違っていると感じますが、それを行う正しい方法です。

79
Humphrey Bogart

Pythonの素晴らしい標準ライブラリが救助に…

import codecs

reader = codecs.getreader("utf-8")
obj = json.load(reader(response))

Py2とpy3の両方で動作します。

ドキュメント: Python 2Python

100
jbg

私は質問が最良の答えだと思うようになりました:)

import json
from urllib.request import urlopen

response = urlopen("site.com/api/foo/bar").read().decode('utf8')
obj = json.loads(response)
66
SergO

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'))
18
Luke Yeager

これは私のために働いています、私はjson()で「リクエスト」ライブラリを使用しました 人間のリクエスト のドキュメントをチェックアウトしてください

import requests

url = 'here goes your url'

obj = requests.get(url).json() 
11
Sarthak Gupta

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以降へのアップグレードを検討してください。

5
PaulMest

flaskマイクロフレームワークを使用しているときにこの問題が発生した場合は、次のようにします。

data = json.loads(response.get_data(as_text=True))

ドキュメントから :「as_textがTrueに設定されている場合、戻り値はデコードされたUnicode文字列になります」

3
cs_stackX

あなたの回避策は実際に私を救った。 Falconフレームワークを使用してリクエストを処理する際に多くの問題が発生していました。これは私のために働いた。リクエストフォームcurl pr httpie

json.loads(req.stream.read().decode('utf-8'))
2
thielyrics

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/

1
Collin Anderson