Skip to main content

Python Enum conversion to Collections and Serialization

· 6 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

This article focuses on the practical necessity of converting an entire enum.Enum class into standard Python collections (list, dict) and preparing them for data interchange formats like JSON. This is essential when presenting options in an API response, generating documentation, or storing structured data.

Setup and Base Enum

We will use a composite Enum structure for these examples, ensuring all conversion methods handle both string and integer values correctly.

from enum import Enum
import json

class ServerState(Enum):
"""Represents server health states."""
ACTIVE = ("A", 100, "Server is operational")
DEGRADED = ("D", 200, "Partial functionality")
OFFLINE = ("O", 300, "Server is down")

# Use __new__ to handle multiple values in the member definition
def __new__(cls, code: str, severity: int, description: str):
obj = object.__new__(cls)
# The canonical value is set here (using the short code)
obj._value_ = code
obj.severity = severity
obj.description = description
return obj

# Annotation: Since we used __new__, ServerState.ACTIVE.value returns "A",
# but we can access the severity and description via custom attributes.

Conversion to List Structures

Converting an Enum into a list is required when presenting options to a user interface or generating documentation.

# Setup
enum_class = ServerState

# Example 1: Enum to List of Raw Values
value_list = [member.value for member in enum_class]
print(f"List of Values: {value_list}")
# Output: ['A', 'D', 'O']

# Example 2: Enum to List of Member Names
name_list = [member.name for member in enum_class]
print(f"List of Names: {name_list}")
# Output: ['ACTIVE', 'DEGRADED', 'OFFLINE']

# Example 3: Enum to List of (Name, Value) Tuples
tuple_list = [(member.name, member.value) for member in enum_class]
print(f"List of Tuples: {tuple_list}")
# Output: [('ACTIVE', 'A'), ('DEGRADED', 'D'), ('OFFLINE', 'O')]

# Example 4: Enum to List of Rich Dictionaries (Using Custom Attributes)
rich_list = [
{
"name": member.name,
"code": member.value,
"severity": member.severity,
"description": member.description
}
for member in enum_class
]
print(f"List of Dictionaries: {json.dumps(rich_list, indent=2)}")

Conversion to Dictionary Structures (Name-Value Mapping)

Dictionaries are essential for rapid lookups and generating key-value mappings suitable for configuration files or database schemas.

# Example 5: Enum to Name -> Value Dictionary
name_to_value_dict = {member.name: member.value for member in enum_class}
print(f"Name -> Value Dict: {name_to_value_dict}")
# Output: {'ACTIVE': 'A', 'DEGRADED': 'D', 'OFFLINE': 'O'}

# Example 6: Enum to Value -> Name Dictionary (Reverse Mapping)
# This is a key step for reverse lookup when only the raw value is available
value_to_name_dict = {member.value: member.name for member in enum_class}
print(f"Value -> Name Dict: {value_to_name_dict}")
# Output: {'A': 'ACTIVE', 'D': 'DEGRADED', 'O': 'OFFLINE'}

# Example 7: Using dict() on the Enum (Often returns a different structure)
# Note: The items() method is often needed to get the expected list of tuples.
print(f"Using dict() on Enum: {dict(enum_class.__members__.items())}")
# Output: {'ACTIVE': <ServerState.ACTIVE: 'A'>, ...}
# Annotation: This returns the members themselves, not just their values.

JSON Serialization and Deserialization

Enums are not JSON-serializable by default. You must explicitly convert them to strings or integers.

Custom JSON Encoder

The cleanest way to handle Enum serialization globally is to use a custom JSONEncoder that automatically converts any encountered Enum object to its raw value.

class EnumEncoder(json.JSONEncoder):
"""Custom JSONEncoder to handle Enum members."""
def default(self, obj):
if isinstance(obj, Enum):
# Always serialize using the raw value
return obj.value
return json.JSONEncoder.default(self, obj)

# Example 8: Serialization (Enum Member to JSON string)
data_to_send = {
"status_code": ServerState.DEGRADED,
"severity_level": ServerState.OFFLINE.severity
}

json_output = json.dumps(data_to_send, cls=EnumEncoder, indent=2)
print(f"Serialized JSON Output:\n{json_output}")
# Output: "status_code": "D", "severity_level": 300

# Example 9: Deserialization (JSON string to Enum Member)
def parse_status(raw_code: str) -> ServerState:
"""Robustly converts a raw string from JSON back into an Enum member."""
# Uses the direct call method which raises ValueError on invalid input
return ServerState(raw_code)

parsed_member = parse_status("A")
print(f"Deserialized Member: {parsed_member}")

Sources and Further Reading

  1. Python Documentation - json Module
  2. Python Documentation - json.JSONEncoder
  3. Python Documentation - Iterating Over Enums
  4. Python Documentation - Accessing Members