AIP-161
Field masks
Often, when updating resources (using an update method as defined in AIP-134 or something reasonably similar), it is desirable to specify exactly which fields are being updated, so that the service can ignore the rest, even if the user sends new values.
It is tempting to define a mask format to handle the precise needs for each API. However, masking requirements evolve, and therefore it is prudent to use a structured syntax. This allows updates to be able to be made transparently, without waiting for UI or client updates.
Guidance
Update methods (AIP-134) must include an update_mask
field. These
are called "field masks", and they use the google.protobuf.FieldMask
type.
Field masks must always be relative to the resource:
Warning: Read masks as a single field on the request message, for
example: google.protobuf.FieldMask read_mask
are DEPRECATED.
message UpdateBookRequest {
// The book to update.
//
// The book's `name` field is used to identify the book to update.
// Format: publishers/{publisher}/books/{book}
Book book = 1 [(google.api.field_behavior) = REQUIRED];
// The list of fields to update.
// Fields are specified relative to the book
// (e.g. `title`, `rating`; *not* `book.title` or `book.rating`).
google.protobuf.FieldMask update_mask = 2;
}
Read-write consistency
Read and write behavior for field masks must be self-consistent if a mask is present:
- If a user updates a resource with a given mask, and then reads the same
resource with the same mask, the exact same data must be returned.
- Exception: Output only fields.
- Similarly, reading a resource with a given mask and then updating the resource with the returned data and the same mask must be a no-op.
Note: This implies that any mask that is valid for either read or write must be valid for both.
Specifying specific fields
Field masks must permit the specification of specific fields in a defined
struct, using the .
character for traversal.
Because field masks are always relative to the resource, direct fields on the
resource require no traversal (examples: title
, rating
). Traversal is used
when resources contain messages (example: author.given_name
).
Note: A user must be able to specify either a field as a whole, or one
of its subfields: author
and author.given_name
are both valid.
Map fields
Field masks may permit the specification of specific fields in a map, if
and only if the map's keys are either strings or integers, using the .
character for traversal.
Field masks should support string keys that contain characters that are problematic for the field mask syntax, using the backtick character.
message Book {
// The name of the book.
// Format: publishers/{publisher}/books/{book}
string name = 1;
// Reviews for the back cover. The key is the author of the review,
// and the value is the text of the review.
//
// Valid field masks: reviews, reviews.smith, reviews.`John Smith`
map<string, string> reviews = 2;
}
Wildcards
Field masks may permit the use of the *
character on a repeated field or
map to indicate the specification of particular sub-fields in the collection:
message Book {
// The name of the book.
// Format: publishers/{publisher}/books/{book}
string name = 1;
// The author or authors of the book.
// Valid field masks: authors, authors.*.given_name, authors.*.family_name
// Invalid field masks: authors.0, authors.0.given_name
repeated Author authors = 2;
}
message Author {
// The author's given name.
string given_name = 1;
// The author's family name.
string family_name = 2;
}
Note: Field masks must not permit accessing a particular element of a
repeated field by index, and must return an INVALID_ARGUMENT
error if
this is attempted.
Output only fields
If a user includes an output only field in an update mask indirectly (by using a wildcard or specifying an overall message that includes an output-only subfield), the service must ignore any output only fields provided as input, even if they are cleared or modified.
If a user directly specifies an output only field in an update mask, the
service should ignore the output only fields provided as input, even if
they are cleared or modified, to permit the same field mask to be used for
input and output. However, the service may choose to error with
INVALID_ARGUMENT
if the field is modified in input.
Invalid field mask entries
When reading data, field masks may ignore entries that point to a value that can not exist (either a field that does not exist, or a map key that the service considers invalid).
When writing data, field masks should return an INVALID_ARGUMENT
error if
an entry points to a value that can not exist; however, the service may
permit deletions.