2

TL,博士使用FieldMask时,HTTP PATCH 应如何传达资源属性的删除?

Google用于实现标准方法的API 设计指南指出,应该使用FieldMask来实现部分更新。下面是我自己设计的更新资源的示例:Test

该服务的 API 为部分更新定义了一个Test资源和一个HTTP PATCH方法 ( UpdateTest)。

// A test resource.
message Test {
  string name = 1;
  google.protobuf.StringValue description = 2;
}

// Request message for update method.
message UpdateTestRequest {
  // The resource name of the test to be updated. 
  string name = 1;
  // Wrap the actual data in a data field.
  Test test = 2;
  // Field mask to support partial updates.
  google.protobuf.FieldMask update_mask = 3;
}

// Partially update a Test resource.
rpc UpdateTest(UpdateTestRequest) returns (google.protobuf.Empty) {
  option (google.api.http) = {
     patch: "v1/{name=tests/*}"
     body: "*"
   };
}

同样设计的服务器实现使用FieldMask来合并资源(原始消息):

updated_test = v1_test_pb2.Test(name = 'Updated')
original_test = v1_test_pb2.Test(
  name = 'Original',
  description = google.protobuf.wrappers_pb2.StringValue(
    value = 'I am Original!')
)

mask = google.protobuf.field_mask_pb2.FieldMask(
  paths = ['name', 'description']
)

# from, to
mask.MergeMessage(updated_test, original_test)
print(updated_test)

最终结果是一个补丁Test资源:

name: "Updated"
description {
  value: "I am Original!"
}

清除该description字段会完全删除该属性:

updated_test = v1_test_pb2.Test(name = 'Updated')
updated_test.ClearField('description')

original_test = v1_test_pb2.Test(
  name = 'Original',
  description = google.protobuf.wrappers_pb2.StringValue(
    value = 'I am Original!')
)

# from, to
mask.MergeMessage(updated_test, original_test)
print(updated_test)

...最终修补的Test资源将是:

name: "Updated"

伟大的。但是如何在 HTTP PATCH 请求中编码呢?

我能想到的唯一“解决方案”是,如果FieldMask包含description但更新的Test资源未提供值,则应使用ClearField将其删除。

这将需要手动访问掩码或Test消息(或两者)中的每个字段,以确定是否应将其删除。这似乎很疯狂,特别是如果资源有很多字段。

4

0 回答 0