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

186 投票
12 回答
167227 浏览
提问于 2025-04-16 22:27

我在用Python 3从一个网址请求一个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中漏掉了什么参数来指定编码呢?

12 个回答

67

我觉得这个问题本身就是最好的答案 :)

import json
from urllib.request import urlopen

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

Python的强大标准库来帮忙了……

import codecs

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

这个方法在Python 2和Python 3中都可以使用。

文档链接:Python 2Python 3

81

HTTP其实就是在发送字节。如果我们说的资源是文本,通常会通过Content-Type这个HTTP头部或者其他方式(比如RFC标准、HTML中的meta http-equiv标签等)来指定字符编码。

urllib这个库本来应该能够把字节编码成字符串,但它实在是太简单了——功能非常有限,也不符合Python的风格。

Dive Into Python 3这本书对这个情况有个概述。

你提到的“变通方法”是可以的——虽然感觉不太对,但其实这是正确的做法。

撰写回答