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

These masks of field names are called "field masks". Fields representing a field mask must use the google.protobuf.FieldMask type. Field masks are most common on Update requests (AIP-134).

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.
  • 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 {
  option (google.api.resource) = {
    type: "library.googleapis.com/Book"
    pattern: "publishers/{publisher}/books/{book}"
  };

  // The name of the book.
  // Format: publishers/{publisher}/books/{book}
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // 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 must 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.

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.

Changelog

  • 2023-10-18: Update guidance for presence of output only fields in update mask.
  • 2023-07-17: Move update_mask guidance to AIP-134.