我正在尝试在ZipFile BytesIO进程中编写一个json。它是这样的:
import io
from zipfile import ZipFile
import json
in_memory_zip = io.BytesIO()
with ZipFile(in_memory_zip, 'w') as zipfile:
with zipfile.open("1/1.json", 'w') as json_file:
data = {'key': 1}
json.dump(data, json_file, ensure_ascii=False, indent=4)
它后来保存在Django文件字段中。但是,它不会将数据dump
到json_file
中。发现很难,因为它不报告错误消息。
您的代码"影子"zipfile
,这本身不会成为问题,但如果稍后在代码中需要zipfile
,则会导致问题。通常,不要隐藏标准库标识符和 Python 关键字。
为什么这是一个问题,我不知道,但它似乎json.dump
期望从文件指针中获得一些ZipFile.open()
得到的类似文件的对象所没有的东西。
这是解决这个问题的方法:
import io
from zipfile import ZipFile
import json
in_memory_zip = io.BytesIO()
with ZipFile(in_memory_zip, 'w') as zf:
with zf.open("1/1.json", 'w') as json_file:
data = {'key': 1}
data_bytes = json.dumps(data, ensure_ascii=False, indent=4).encode('utf-8')
json_file.write(data_bytes)
原始代码失败的原因是ZipFile
期望二进制数据作为输入,而json.dump
期望一个接受"文本"数据的类似文件的对象(str
,而不是bytes
(。您可能会认为zf.open()
返回的对象是使用"wb"
模式打开的文件。
因此,这里要做的正确的做法是包装类似文件的对象,以将面向文本的输出呈现给json.dump
。而且,由于任何文本都必须编码为字节,因此您必须从encodings
库中获取解决方案。
所以,这有效:
import io
from zipfile import ZipFile
import json
import encodings
in_memory_zip = io.BytesIO()
with ZipFile(in_memory_zip, 'w') as zipfile:
with zipfile.open("1/1.json", 'w') as json_file:
data = {'key': 1}
json_writer = encodings.utf_8.StreamWriter(json_file)
# JSON spec literally fixes interchange encoding as UTF-8: https://datatracker.ietf.org/doc/html/rfc8259#section-8.1
json.dump(data, json_writer, ensure_ascii=False, indent=4)