让 JSON 对象接受字节或让 urlopen 输出字符串

对于 Python3,我从 URL 请求一个 json 文档。

response = urllib.request.urlopen(request)

response对象是具有 readreadline方法的类文件对象。通常可以创建一个 JSON 对象,并以文本模式打开一个文件。

obj = json.load(fp)

我想做的是:

obj = json.load(response)

然而,当 urlopen 以二进制模式返回文件对象时,这不起作用。

解决办法当然是:

str_response = response.read().decode('utf-8')
obj = json.loads(str_response)

但这感觉很糟糕。

有没有更好的方法可以将字节文件对象转换为字符串文件对象?或者我是否缺少 urlopenjson.load的任何参数来给出编码?

159969 次浏览

HTTP 发送字节。如果所涉及的资源是文本,那么字符编码通常由 Content-Type HTTP 头或其他机制(一个 RFC,HTML meta http-equiv,...)指定。

urllib 应该知道如何将字节编码为字符串,但它太天真了ーー它是一个功能极其不足、非 Python 的库。

Dive Into Python3 提供了有关情况的概述。

你的“变通方法”很好ーー尽管感觉不对,但这是正确的方法。

Python 奇妙的标准库拯救了..。

import codecs


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

可以同时使用 py2和 py3。

医生: 巨蟒2蟒蛇3

我认为这个问题是最好的答案:)

import json
from urllib.request import urlopen


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

刚刚发现这个简单的方法可以将 HttpResponse 内容作为 json

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"}

希望这能帮到你

对于任何试图使用 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'))

如果您在使用烧瓶微框架时遇到了这个问题,那么您可以这样做:

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

来自 docs : “如果 as _ text 设置为 True,返回值将是解码的 unicode 字符串”

这一个为我工作,我用“请求”库与 json()检查在 对人类的要求的文档

import requests


url = 'here goes your url'


obj = requests.get(url).json()

我在使用 Python 3.4.3 & 3.5.2和 Django 1.11.3时遇到了类似的问题。然而,当我升级到 Python3.6.1时,问题就消失了。

你可以在这里了解更多: Https://docs.python.org/3/whatsnew/3.6.html#json

如果您没有绑定到特定的 Python 版本,只需考虑升级到3.6或更高版本即可。

你的变通方法救了我一命。我在使用 Falcon 框架处理请求时遇到了很多问题。这招对我很管用。Req 是请求表单 curl pr httpie

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

我使用下面的程序来使用 json.loads()

import urllib.request
import json
endpoint = 'https://maps.googleapis.com/maps/api/directions/json?'
api_key = 'AIzaSyABbKiwfzv9vLBR_kCuhO7w13Kseu68lr0'
origin = input('where are you ?').replace(' ','+')
destination = input('where do u want to go').replace(' ','+')
nav_request = 'origin={}&destination={}&key={}'.format(origin,destination,api_key)
request = endpoint + nav_request
response = urllib.request.urlopen(request).read().decode('utf-8')
directions = json.loads(response)
print(directions)

这将把字节数据传输到 json 中。

import io


obj = json.load(io.TextIOWrapper(response))

TextIOWrapper 优于编解码器的模块读取器

在 Python 3.6中,可以使用 json.loads()直接反序列化 bytes对象(编码必须是 UTF-8、 UTF-16或 UTF-32)。因此,只使用标准库中的模块,您可以:

import json
from urllib import request


response = request.urlopen(url).read()
data = json.loads(response)