Using enums as fields of a JSON payloads is a great way to force provided values into one of a limited number of self-documenting fields.
However, integer-valued enums can make it more difficult to inspect payloads and debug endpoint calls, especially if the client and server are using different code bases.
For most applications, the development benefits of using string-valued enums vastly outweigh the minimal performance/bandwidth tradeoffs.
Creating a string-valued enum for use with pydantic/FastAPI that is properly encoded in the OpenAPI spec is
as easy as inheriting from
str in addition to
from enum import Enum class MyEnum(str, Enum): value_a = "value_a" value_b = "value_b"
One nuisance with this approach is that if you rename one of the enum values (for example, using an IDE), you can end up with the name and value differing, which may lead to confusing errors.
For example, if you refactored the above as follows (forgetting to çhange the associated values), you’ll get pydantic parsing errors if you use the new names instead of the values in JSON bodies:
from enum import Enum class MyEnum(str, Enum): choice_a = "value_a" # pydantic would only parse "value_a" to MyEnum.choice_a choice_b = "value_b"
The standard library’s
enum package provides a way to automatically generate values:
auto will generate integer values, but this behavior can be overridden
and the official python docs include a detailed section about
how to do this.
Rather than repeating this definition in each new project, to reduce boilerplate
you can just inherit from
fastapi_utils.enums.StrEnum directly to get this behavior:
from enum import auto from fastapi_utils.enums import StrEnum class MyEnum(StrEnum): choice_a = auto() choice_b = auto() assert MyEnum.choice_a.name == MyEnum.choice_a.value == "choice_a" assert MyEnum.choice_b.name == MyEnum.choice_b.value == "choice_b"
You can also use
fastapi_utils.enums.CamelStrEnum to get camelCase values:
from enum import auto from fastapi_utils.enums import CamelStrEnum class MyEnum(CamelStrEnum): choice_one = auto() choice_two = auto() assert MyEnum.choice_a.name == MyEnum.choice_a.value == "choiceOne" assert MyEnum.choice_b.name == MyEnum.choice_b.value == "choiceTwo"