Batu Lab NotesPractical developer guides

Serialize enum names instead of implementation values

By Batu · English technical notes

Also published in our Blogger archive.

When an external JSON format identifies a state by its symbolic label, serialize Status.COMPLETE.name rather than its implementation value. This example produces {"status": "COMPLETE"} even though the enum’s current value is the integer 20. On input, Status[loaded["status"]] deliberately interprets the stored string as a member name and reconstructs the same member.

This separates the JSON representation from a value chosen for implementation logic. It is only a compatibility benefit if member names are treated as part of the format contract. Renaming COMPLETE will break old payloads unless the reader includes an explicit migration or compatibility mapping. Names are also not automatically safer than values: validate payload structure and handle missing or unknown names at the boundary where data enters the program.

json.dumps can encode the dictionary because its value is the ordinary string returned by .name. For an ordinary Enum member such as this article’s Status, encoding the member itself requires a conversion such as this one or a custom encoder. This limitation does not apply to IntEnum or float-derived enum members: the default JSON encoder supports those numeric enum types. The assertions verify the exact dictionary content and enum identity after a JSON round trip. They do not prove persistence compatibility across future enum changes. Enum is available from Python 3.4, while the JSON module is part of the standard library.

AI assistance disclosure: this article was drafted with AI assistance and should be reviewed in the context of its target Python version.

Python enum documentation documents enum member names and name-based lookup. Python json documentation documents JSON encoding, decoding, and support for numeric enum types.

import json
from enum import Enum


class Status(Enum):
    PENDING = 10
    COMPLETE = 20


status = Status.COMPLETE
payload = json.dumps({"status": status.name}, sort_keys=True)
loaded = json.loads(payload)
restored = Status[loaded["status"]]

assert loaded == {"status": "COMPLETE"}
assert restored is Status.COMPLETE

print(f"{payload} -> {restored.value}")
{"status": "COMPLETE"} -> 20