AIP-126
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:
// A representation of a book.
message Book {
// Other fields...
// Possible formats in which the book may be published.
enum Format {
// Default value. This value is unused.
FORMAT_UNSPECIFIED = 0;
// The printed format, in hardback.
HARDBACK = 1;
// The printed format, in paperback.
PAPERBACK = 2;
// An electronic book format.
EBOOK = 3;
// An audio recording.
AUDIOBOOK = 4;
}
// The format of the book.
Format format = 99;
// Other fields...
}
- All enum values must use
UPPER_SNAKE_CASE
. - The first value of the enum should be the name of the enum itself
followed by the suffix
_UNSPECIFIED
.- An exception to this rule is if there is a clearly useful zero value. In
particular, if an enum needs to present an
UNKNOWN
, it is usually clearer and more useful for it to be a zero value rather than having both.
- An exception to this rule is if there is a clearly useful zero value. In
particular, if an enum needs to present an
- 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.
- The non-zero values of such a nested enum definition should not be prefixed by the name
of the enum itself. This generally requires users to write
MyState.MYSTATE_ACTIVE
in their code, which is unnecessarily verbose.
- The non-zero values of such a nested enum definition should not be prefixed by the name
of the enum itself. This generally requires users to write
- Enums which will be used by multiple messages should be defined at the package level and
should be defined at the bottom of the proto file (see AIP-191).
- Some languages (including C++) hoist enum values into the parent namespace, which can result in conflicts for enums with the same values in the same proto package. To avoid sharing values, APIs should prefix package-level enum values with the name of the enum.
- 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.
Additionally, enums should not be used when there is a competing, widely-adopted standard representation (such as with language codes or media types).
Note: If an enumerated value needs to be shared across APIs, an enum may be used, but the assignment between enum values and their corresponding integers must match.
Alternatives
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 kebab-case
for
their values.
For enumerated values where there is a competing, widely-adopted standard representation (generally, but not necessarily, a string), 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.
Boolean fields may be used in situations where it is clear that no further
flexibility will be needed. The default value must be false
.
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).
Further reading
- For states, a special type of enum, see AIP-216.