AIP-149
Unset field values
In many messages, many fields are optional: the user is not required to provide them, or for output fields, the service might not populate the field.
In most cases, there is no meaningful difference between setting it to a
default value (such as 0
) as opposed to not setting it at all; however,
occasionally this distinction is meaningful.
Guidance
Services defined in protocol buffers should use the optional
keyword for
primitives if and only if it is necessary to distinguish setting the field to
its default value (0
, false
, or empty string) from not setting it at all:
// A representation of a book in a library.
message Book {
option (google.api.resource) = {
type: "library.googleapis.com/Book"
pattern: "publishers/{publisher}/books/{book}"
};
// The name of the book.
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
// The rating for the book, from 0 to 5.
// 0 is distinct from no rating.
optional int32 rating = 2;
}
Important: Services should not need to distinguish between the default
value and unset most of the time; if an alternative design does not require
such a distinction, it is usually preferred. In practice, this means optional
should only ever be used for integers and floats.
Important: Tracking field presence is not the same as documenting API
field behavior as defined in AIP-203. For example, a field labeled with
optional
for presence tracking may also be annotated as
google.api.field_behavior = REQUIRED
if the field must be set. If you only
want to document the server perceived behavior of a field, read AIP-203.
Backwards compatibility
It is a backwards incompatible change to add or remove the optional
qualifier
to an existing field. This is because the compiled src API is changed (in some
languages). For example, in Golang, adding optional
changes the field type of
primitives to be the pointer variant of their original type, e.g. a field
formerly of type string
becomes *string
, etc. Accordingly, this change
requires that both clients and servers update their usage of the changed field
in unison, which is risky and error prone. Additional information is
documented by Protobuf.
Rationale
field behavior and optional
The field behavior annotation and optional
label are not mutually exclusive,
because they address different problems. The former,
google.api.field_behavior
, focuses on communicating the server's perception of
a field within the API e.g. if it is required or not, if it is immutable, etc.
The latter, proto3's optional
, is a wire format and code generation option
that is strictly for toggling field presence tracking. While it might be
confusing for a field to be simultaneously annotated with
google.api.field_behavior = REQUIRED
and labeled as optional
, they are
unrelated in practice and can reasonably be used together.
Changelog
- 2024-06-05: Add backwards compatibility considerations
- 2023-06-20: Differentiate from field behavior documentation