MIME データを JSON に格納したら復元に戸惑った話。
背景
import json
import base64
import os
import sys
filepath = sys.argv[1]
filename = os.path.basename(filepath)
# 拡張子を取得
type = os.path.splitext(filename)[1][1:]
data = {}
with open(filepath, mode='rb') as file:
img = file.read()
data['type'] = type
data['filename'] = filename
data['file'] = base64.encodebytes(img).decode('utf-8')
として、
print(data['file'])
とすると、
UEsDBBQAAAgAADAl71afAy7EKwAAACsAAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQub2Fz
aXMub3BlbmRvY3VtZW50LmdyYXBoaWNzUEsDBBQAAAgAADAl71YAAAAAAAAAAAAAAAAcAAAAQ29u
ZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAHwAAAENv
bmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAAMCXvVgAAAAAAAAAAAAAAABoA
AABDb25maWd1cmF0aW9uczIvdG9vbHBhbmVsL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAHAAA
AENvbmZpZ3VyYXRpb25zMi9wcm9ncmVzc2Jhci9QSwMEFAAACAAAMCXvVgAAAAAAAAAAAAAAABoA
AABDb25maWd1cmF0aW9uczIvc3RhdHVzYmFyL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAGAAA
のようになる。これは、base64.encodebytes(s) によって RFC2045 (MIME) に従った 76 文字ごとに改行されたもの。
print(jsonobject["file"])
とすると
UEsDBBQAAAgAADAl71afAy7EKwAAACsAAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQub2Fz\n
aXMub3BlbmRvY3VtZW50LmdyYXBoaWNzUEsDBBQAAAgAADAl71YAAAAAAAAAAAAAAAAcAAAAQ29u\n
ZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAHwAAAENv\n
bmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAAMCXvVgAAAAAAAAAAAAAAABoA\n
AABDb25maWd1cmF0aW9uczIvdG9vbHBhbmVsL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAHAAA\n
AENvbmZpZ3VyYXRpb25zMi9wcm9ncmVzc2Jhci9QSwMEFAAACAAAMCXvVgAAAAAAAAAAAAAAABoA\n
.
.
.
となった(わかりやすいように\nの後ろに改行を入れているが、実際は巨大な1行となっている)。
これは、JSONの規格で改行を入れることができないために改行がエスケープされている。
そのうえで、
print(json.dumps(data))
として、以下のように出力されたものを使ってデータ交換を行う。
(b'tEXt', b'{"type": "odg", "filename": "x2.odg", "file":"
UEsDBBQAAAgAADAl71afAy7EKwAAACsAAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQub2Fz\\n
aXMub3BlbmRvY3VtZW50LmdyYXBoaWNzUEsDBBQAAAgAADAl71YAAAAAAAAAAAAAAAAcAAAAQ29u\\n
ZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAHwAAAENv\\n
bmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAAMCXvVgAAAAAAAAAAAAAAABoA\\n
AABDb25maWd1cmF0aW9uczIvdG9vbHBhbmVsL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAHAAA\\n
AENvbmZpZ3VyYXRpb25zMi9wcm9ncmVzc2Jhci9QSwMEFAAACAAAMCXvVgAAAAAAAAAAAAAAABoA\\n
.
.
.
さて、JSONデータを受け取った方はどうしたら RFC2045 (MIME) に従った 76 文字ごとに改行されたものに復元できるかな?
解決方法
print(jsonobject["file"].encode("utf-8").decode("unicode-escape"))
得られるもの
UEsDBBQAAAgAADAl71afAy7EKwAAACsAAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQub2Fz
aXMub3BlbmRvY3VtZW50LmdyYXBoaWNzUEsDBBQAAAgAADAl71YAAAAAAAAAAAAAAAAcAAAAQ29u
ZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAHwAAAENv
bmZpZ3VyYXRpb25zMi9pbWFnZXMvQml0bWFwcy9QSwMEFAAACAAAMCXvVgAAAAAAAAAAAAAAABoA
AABDb25maWd1cmF0aW9uczIvdG9vbHBhbmVsL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAHAAA
AENvbmZpZ3VyYXRpb25zMi9wcm9ncmVzc2Jhci9QSwMEFAAACAAAMCXvVgAAAAAAAAAAAAAAABoA
AABDb25maWd1cmF0aW9uczIvc3RhdHVzYmFyL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAGAAA
AENvbmZpZ3VyYXRpb25zMi90b29sYmFyL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAGAAAAENv
bmZpZ3VyYXRpb25zMi9mbG9hdGVyL1BLAwQUAAAIAAAwJe9WAAAAAAAAAAAAAAAAGgAAAENvbmZp
.
.
.
python3 は信号処理してるとムダな encode や decode が重奏して頭が痒くなりますね。