Pythonのjsonモジュールを使ってJSON化する際、その中の値にJSONに変換できない値があるとTypeErrorとなってしまう。
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/opt/ng/symdon/pages/posts/1616552904/example.py", line 27, in <module> dumps( File "/usr/local/Cellar/[email protected]/3.8.8_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/__init__.py", line 231, in dumps return _default_encoder.encode(obj) File "/usr/local/Cellar/[email protected]/3.8.8_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/encoder.py", line 199, in encode chunks = self.iterencode(o, _one_shot=True) File "/usr/local/Cellar/[email protected]/3.8.8_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/encoder.py", line 257, in iterencode return _iterencode(o, 0) File "/usr/local/Cellar/[email protected]/3.8.8_1/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/encoder.py", line 179, in default raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type Example1Enum is not JSON serializable
型ヒントを有効に使おうとするとEnumの値はそのまま保持したほうがよいため json.dumps()する際にEnumの値が含まれているケースがある。そのためEnumの 値をJSON化する場合には.valueで値を取得しそれをJSON化するための JSONEncoderを書いた。
from json import JSONEncoder
class EnumAvailableJSONEncoder(JSONEncoder):
"""Enumクラスの値を.valueの値にしてエンコードする"""
def default(self, o):
if isinstance(o, Enum):
return o.value
return super().default(o)
isinstance()でEnumのインスタンスかどうかを確認しそうであれば .value
で値を取得、そうでなければそのままの値をJSON化している。
例としてEnumを2つ実装し、それらを変換できるかを確認する。
from json import JSONEncoder
from enum import Enum
from json import dumps
class EnumAvailableJSONEncoder(JSONEncoder):
"""Enumクラスの値を.valueの値にしてエンコードする"""
def default(self, o):
if isinstance(o, Enum):
return o.value
return super().default(o)
class Example1Enum(Enum):
foo = "Foo"
bar = "Bar"
baz = "Baz"
class Example2Enum(Enum):
foo = "Foo"
bar = "Bar"
baz = "Baz"
return dumps(
{"ex1": Example1Enum.foo, "ex2": Example1Enum.bar},
cls=EnumAvailableJSONEncoder,
)
{"ex1": "Foo", "ex2": "Bar"}
期待どおりに変換された。