AIP-161
```org
字段掩码
在更新资源时(使用AIP-134中定义的更新方法或类似的方法),通常需要明确指定哪些字段正在被更新,以便服务可以忽略其余字段,即使用户发送了新值。
虽然为每个API定义特定的掩码格式来处理精确需求很诱人,但由于掩码需求会不断演变,因此使用结构化语法更为明智。这允许透明地进行更新,而无需等待UI或客户端更新。
指导
这些字段名称的掩码称为“字段掩码”。表示字段掩码的字段**必须**使用`google.protobuf.FieldMask`类型。字段掩码在更新请求(AIP-134)中最为常见。
字段掩码**必须**始终相对于资源:
警告: 读取掩码作为请求消息中的单个字段,例如:`google.protobuf.FieldMask read_mask`,**已弃用**。
```proto message UpdateBookRequest { / 要更新的书籍。 / / 书籍的`name`字段用于标识要更新的书籍。 / 格式:publishers/{publisher}/books/{book} Book book = 1 [(google.api.field_behavior) = REQUIRED];
/ 要更新的字段列表。 / 字段相对于书籍指定 // (例如:`title`,`rating`;*不是* `book.title`或`book.rating`)。 google.protobuf.FieldMask update_mask = 2; } ```
读写一致性
如果存在掩码,字段掩码的读写行为**必须**自洽:
- 如果用户使用给定的掩码更新资源,然后使用相同的掩码读取相同的资源,**必须**返回完全相同的数据。
- 例外:仅输出字段。
- 类似地,使用给定的掩码读取资源,然后使用返回的数据和相同的掩码更新资源**必须**是无操作的。
注意: 这意味着任何对读取或写入有效的掩码**必须**对两者都有效。
指定特定字段
字段掩码**必须**允许使用`.`字符遍历指定定义结构中的特定字段。
由于字段掩码始终相对于资源,资源上的直接字段不需要遍历(例如:`title`,`rating`)。当资源包含消息时使用遍历(例如:`author.given_name`)。
注意: 用户**必须**能够指定整个字段或其子字段之一:`author`和`author.given_name`都是有效的。
映射字段
字段掩码**可以**允许使用`.`字符遍历指定映射中的特定字段,前提是映射的键是字符串或整数。
字段掩码**应该**支持包含对字段掩码语法有问题的字符的字符串键,使用反引号字符。
```proto message Book { / 书籍的名称。 / 格式:publishers/{publisher}/books/{book} string name = 1;
/ 封底的评论。键是评论的作者, / 值是评论的文本。 / / 有效的字段掩码:reviews, reviews.smith, reviews.`John Smith` map<string, string> reviews = 2; } ```
通配符
字段掩码**可以**允许在重复字段或映射上使用`*`字符来表示集合中特定子字段的指定:
```proto message Book { option (google.api.resource) = { type: “library.googleapis.com/Book” pattern: “publishers/{publisher}/books/{book}” };
/ 书籍的名称。 / 格式:publishers/{publisher}/books/{book} string name = 1 [(google.api.field_behavior) = IDENTIFIER];
/ 书籍的作者或作者们。 / 有效的字段掩码:authors, authors.*.given_name, authors.*.family_name // 无效的字段掩码:authors.0, authors.0.given_name repeated Author authors = 2; }
message Author { // 作者的名字。 string given_name = 1;
// 作者的姓氏。 string family_name = 2; } ```
注意: 字段掩码**不得**允许通过索引访问重复字段的特定元素,并且如果尝试这样做,**必须**返回`INVALID_ARGUMENT`错误。
仅输出字段
如果用户通过使用通配符或指定包含仅输出子字段的整个消息间接地在更新掩码中包含仅输出字段,服务**必须**忽略作为输入提供的任何仅输出字段,即使它们被清除或修改。
如果用户直接在更新掩码中指定仅输出字段,服务**必须**忽略作为输入提供的仅输出字段,即使它们被清除或修改,以允许相同的字段掩码用于输入和输出。
无效的字段掩码条目
在读取数据时,字段掩码**可以**忽略指向不存在的值的条目(无论是字段不存在,还是服务认为无效的映射键)。
在写入数据时,如果条目指向不存在的值,字段掩码**应该**返回`INVALID_ARGUMENT`错误;然而,服务**可以**允许删除。
变更日志
- **2023-10-18**:更新了关于更新掩码中存在仅输出字段的指导。
- **2023-07-17**:将`update_mask`指导移至AIP-134。
```