在JSON中序列化base64编码数据

fro*_*llo 31 base64 serialization json python-3.x

我正在编写一个脚本来自动化演示数据,我需要在JSON中序列化一些数据.这个数据的一部分是一个图像,所以我在base64编码它,但当我尝试运行我的脚本时,我得到:

Traceback (most recent call last):
  File "lazyAutomationScript.py", line 113, in <module>
    json.dump(out_dict, outfile)
  File "/usr/lib/python3.4/json/__init__.py", line 178, in dump
    for chunk in iterable:
  File "/usr/lib/python3.4/json/encoder.py", line 422, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "/usr/lib/python3.4/json/encoder.py", line 396, in _iterencode_dict
    yield from chunks
  File "/usr/lib/python3.4/json/encoder.py", line 396, in _iterencode_dict
    yield from chunks
  File "/usr/lib/python3.4/json/encoder.py", line 429, in _iterencode
    o = _default(o)
  File "/usr/lib/python3.4/json/encoder.py", line 173, in default
    raise TypeError(repr(o) + " is not JSON serializable")
  TypeError: b'iVBORw0KGgoAAAANSUhEUgAADWcAABRACAYAAABf7ZytAAAABGdB...
     ...
   BF2jhLaJNmRwAAAAAElFTkSuQmCC' is not JSON serializable
Run Code Online (Sandbox Code Playgroud)

据我所知,base64编码的任何东西(在这种情况下是一个PNG图像)只是一个字符串,所以它应该导致问题到序列化.我错过了什么?

spk*_*pky 65

您必须小心数据类型.

如果您读取二进制图像,则会得到字节.如果你在base64中编码这些字节,你会再次得到......字节!(参见b64encode文档)

json无法处理原始字节,这就是你得到错误的原因.

我刚刚写了一些例子,有评论,我希望它有所帮助:

from base64 import b64encode
from json import dumps

ENCODING = 'utf-8'
IMAGE_NAME = 'spam.jpg'
JSON_NAME = 'output.json'

# first: reading the binary stuff
# note the 'rb' flag
# result: bytes
with open(IMAGE_NAME, 'rb') as open_file:
    byte_content = open_file.read()

# second: base64 encode read data
# result: bytes (again)
base64_bytes = b64encode(byte_content)

# third: decode these bytes to text
# result: string (in utf-8)
base64_string = base64_bytes.decode(ENCODING)

# optional: doing stuff with the data
# result here: some dict
raw_data = {IMAGE_NAME: base64_string}

# now: encoding the data to json
# result: string
json_data = dumps(raw_data, indent=2)

# finally: writing the json string to disk
# note the 'w' flag, no 'b' needed as we deal with text here
with open(JSON_NAME, 'w') as another_open_file:
    another_open_file.write(json_data)
Run Code Online (Sandbox Code Playgroud)


Fil*_*ale 12

我缺少什么?

错误是大喊 abinary不是 JSON 可序列化的。

from base64 import b64encode

# *binary representation* of the base64 string
assert b64encode(b"binary content")                 == b'YmluYXJ5IGNvbnRlbnQ='

# base64 string
assert b64encode(b"binary content").decode('utf-8') ==  'YmluYXJ5IGNvbnRlbnQ='
Run Code Online (Sandbox Code Playgroud)

后者绝对是“JSON 可序列化”,因为它是二进制b"binary content".


ssu*_*tin 8

替代解决方案是使用自定义编码器动态编码内容:

import json
from base64 import b64encode

class Base64Encoder(json.JSONEncoder):
    # pylint: disable=method-hidden
    def default(self, o):
        if isinstance(o, bytes):
            return b64encode(o).decode()
        return json.JSONEncoder.default(self, o)
Run Code Online (Sandbox Code Playgroud)

定义后,您可以执行以下操作:

m = {'key': b'\x9c\x13\xff\x00'}
json.dumps(m, cls=Base64Encoder)
Run Code Online (Sandbox Code Playgroud)

它将产生:

'{"key": "nBP/AA=="}'
Run Code Online (Sandbox Code Playgroud)