Enumerations
It is common for a field to only accept or provide a discrete and limited set of values. In these cases, it can be useful to use enumerations (generally abbreviated “enums”) in order to clearly communicate what the set of allowed values are.
Guidance
APIs may expose enum objects for sets of values that are expected to change infrequently:
- All enum values should use a consistent case format across an organization. In many cases, this is dictated by the IDL the organization uses.
- Enums should document whether the enum is frozen or they expect to add values in the future.
When to use enums
Enums can be more accessible and readable than strings or booleans in many cases, but they do add overhead when they change. Therefore, enums should receive new values infrequently. While the definition of “infrequently” may change based on individual use cases, a good rule of thumb is no more than once a year. For enums that change frequently, the API should use a string and document the format.
Alternatives
Enums should not be used when there is a competing, widely-adopted standard representation (such as with language codes or media types). Instead, that standard representation should be used. This is true even if only a small subset of values are permitted, because using enums in this situation often leads to frustrating lookup tables when trying to use multiple APIs together.
For enumerated values where the set of allowed values changes frequently, APIs
should use a string
field instead, and must document the allowed
values. String fields with enumerated values should use a uniform case
system (snake_case
, kebab-case
, etc.) throughout an organization.
Boolean fields may be used in situations where it is clear that no further
flexibility will be needed. The default value must be false
.
Compatibility
Adding values to an enum has the potential to be disruptive to existing
clients. Consider code written against the Format
enum in an earlier version
where only the first two options were available:
Services may add new values to existing enums; however, they should add enums carefully; think about what will happen if a client system does not know about a new value.
Additionally, in IDLs where enum values are presented in a specific order, services should only add new values to the end. An exception to this rule is if the enum conforms to an external standard (for example, an enum representing HTTP status codes would add a new 3xx value alongside the others, not at the end).
Interface Definitions
- The zero value of the enum should be the name of the enum itself followed
by the suffix
_UNSPECIFIED
. The service may either allow or prohibit use of this value. - Enums which will only be used in a single message should be nested within that message. In this case, the enum should be declared immediately before it is used.
- If multiple enums are in the same namespace, they must not share any values. (This is because enums do not provide their own namespace for their values in some languages.)
- If an enumerated value needs to be shared across APIs, an enum may be used, but the assignment between the value names and the tag numbers must match.
Note: When using protocol buffers, it is impossible to distinguish between
false
and unset. If this is a requirement, an enum may be a better design
choice (although google.protobuf.BoolValue
is also available).
- Enumerated fields should be strings.
- If the enum is optional, The
null
value should be used as the empty value, and should be the first value specified.
Note: If null
is a valid value, OpenAPI 3.0 also requires that
nullable: true
is specified for the field.
Further reading
- For states, a special type of enum, see AEP-216.