简体   繁体   English

如何在 Zipfile.open 进程中转储 json?

[英]How to json dump inside Zipfile.open process?

I am trying to write a json inside a ZipFile BytesIO process.我正在尝试在 ZipFile BytesIO 进程中编写 json 。 It goes like this:它是这样的:

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)

It is later saved in a Django File field.它稍后保存在 Django 文件字段中。 However it does not dump the data into the json_file .但是,它不会将数据dumpjson_file中。 Finds it hard since it does not report an error message.发现很难,因为它不报告错误消息。

Your code 'shadows' zipfile , which won't be a problem by itself, but would cause problems if you needed zipfile later in your code.您的代码 'shadows' zipfile ,这本身不会成为问题,但如果您稍后在代码中需要zipfile ,则会导致问题。 In general, don't shadow standard library identifiers and Python keywords.通常,不要隐藏标准库标识符和 Python 关键字。

Why it's a problem, I don't know, but it appears json.dump expects something from the file pointer that the file-like object that ZipFile.open() gets you doesn't have.为什么这是一个问题,我不知道,但看起来json.dump期望来自文件指针的东西,而ZipFile.open()获得的类文件对象没有。

This is how to get around that:这是解决这个问题的方法:

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)

The reason original code fails is that ZipFile expects binary data as input, while json.dump expects a file-like object that accepts "text" data ( str , not bytes ).原始代码失败的原因是ZipFile期望二进制数据作为输入,而json.dump期望接受“文本”数据( str ,而不是bytes )的类似文件的 object 。 You may think of the object that zf.open() returns as if it is a file that's open with "wb" mode.您可能会想到zf.open()返回的 object 就好像它是以"wb"模式打开的文件一样。

So the right thing to do here is to wrap the file-like object to present text-oriented output to json.dump .所以这里正确的做法是包装类似文件的 object 以呈现面向文本的 output 到json.dump And, as any text is has to be encoded to become bytes, you have to grab the solution from encodings library.而且,由于任何文本都必须编码为字节,因此您必须从encodings库中获取解决方案。

So, this works:所以,这有效:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM