web-dev-qa-db-fra.com

Sérialiser en JSON une donnée encodée en base64

J'écris un script pour automatiser la génération de données pour une démo et j'ai besoin de sérialiser dans un JSON des données. Une partie de ces données est une image, je l'ai donc encodée en base64, mais lorsque j'essaie d'exécuter mon script, j'obtiens:

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

Pour autant que je sache, un encodage en base64 (quelle que soit l'image PNG, dans ce cas) n'est qu'une chaîne, donc cela devrait poser un problème de sérialisation. Qu'est-ce que je rate?

31
frollo

Vous devez faire attention aux types de données.

Si vous lisez une image binaire, vous obtenez des octets. Si vous encodez ces octets en base64, vous obtenez à nouveau ... octets! (voir la documentation sur b64encode )

json ne peut pas gérer les octets bruts, c'est pourquoi vous obtenez l'erreur.

Je viens d'écrire un exemple, avec des commentaires, j'espère que ça aide:

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)
60
spky