更新来自protobuf的数据

huangapple go评论93阅读模式
英文:

Updating data from protobuf

问题

我正在构建一个具有多个不相关组件的微服务系统,并且我目前正在尝试找出如何根据提供的protobuf数据来实现知道对象上应该更新哪些字段。

流程如下:

  1. 客户端向API发送JSON请求。
  2. API将JSON数据转换为protobuf结构,然后将其发送到负责处理的微服务。
  3. 微服务从API接收数据并对其执行任何操作,在这种情况下,我正在尝试更改MySQL表中的单个值,例如客户的电子邮件地址。

现在,我遇到的问题是,由于protobuf(可以理解)不允许使用指针,因此protobuf对象将包含未提供的所有内容的零值。这意味着如果客户要更新他们的电子邮件地址,我无法知道他们是否还将IncludeInMailLists设置为false - 或者它是否只是未提供(具有其零值)而不应更改。

问题是:我如何从protobuf对象中知道一个值是明确设置为0,还是未提供?

我目前的解决方案基本上是拥有一个特殊的UpdateCustomer对象,该对象还具有一个指定微服务应关注的字段的数组Fields,但感觉不是很好。

肯定已经有人解决过这个问题了。我应该如何实现它?

英文:

I'm building a microservice system with multiple disconnected components, and I'm currently trying to find out how to implement knowing which fields on an object should be updated based on the protobuf data provided.

The flow is this:

  1. The client sends a JSON-request to an API.
  2. The API translates the JSON-data into a protobuf struct, which is then sent along to the microservice responsible for handling it.
  3. The microservice receives the data from the API and performs any action on it, in this case, I'm trying to change a single value in a MySQL table, such as a client's email address.

Now, the problem I have is that since protobuf (understandably) doesn't allow pointers, the protobuf object will contain zero-values for everything not provided. This means that if a customer wants to update their email address, I can't know if they also set IncludeInMailLists to false - or if it was simply not provided (having its zero-value) and shouldn't change.

The question is: how will I - from the protobuf object - know if a value is expressively set to 0, or just not provided?

My current solution is pretty much having a special UpdateCustomer-object which also has an array of Fields specifying which fields the microservice should care about, but it feels like bad solution.

Someone must have solved this better already. How should I implement it?

答案1

得分: 9

Protobufs字段掩码是一种方法。

https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.FieldMask

https://github.com/golang/protobuf/issues/225

但是,如果你正在使用grpc,那么有一种(某种程度上)内置的方法。

Grpc包装器

自从proto3(protobufs v3)以来,没有区分未设置的原始类型和设置为“零值”(false、0、“”等)的原始类型。

相反,你可以使用对象或者在protobufs语言中称为“message”的对象,因为对象可以是nil/null。你没有提到你正在使用的编程语言,但希望这些示例能够让你理解。

给定一个RPC服务,例如:

import "google/protobuf/wrappers.proto";

service Users {
    rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse)
}

message UpdateUserRequest {
    int32 user_id = 1;
    google.protobuf.StringValue email = 2;
}

message UpdateUserResponse {}

注意 import "google/protobuf/wrappers.proto"; 是重要的。
它让你可以访问google protobufs包装器的源代码在这里。这些不是具有允许你测试是否存在的方法的对象。

在Java中,Grpc生成的代码提供了诸如.hasEmail()的方法,如果值存在,则返回true。对于未设置的值,getter仍然会返回零值。我认为golang版本使用指针,你可以测试是否为nil,而不是使用显式的hasX()方法。

在这个github问题中有更多信息/讨论。

英文:

Protobufs field masks are one way.

https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.FieldMask

https://github.com/golang/protobuf/issues/225

But if you are using grpc then there's a (sort of) built in way.

Grpc wrappers

Since proto3 (protobufs v3) there's been no distinction between a primitive that is not set, and a primitive that's been set to the "zero value" (false, 0, "", etc).

Instead you can use objects or in protobufs language a "message", as objects can be nil / null. You've not mentioned what language you are working in but hopefully these examples make sense.

Given an RPC service such as:

import "google/protobuf/wrappers.proto";

service Users {
    rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse)
}

message UpdateUserRequest {
    int32 user_id = 1;
    google.protobuf.StringValue email = 2;
}

message UpdateUserResponse {}

Note the import "google/protobuf/wrappers.proto"; is important.
It given you access to the google protobufs wrappers source code here. These are not objects that have methods that allow you to test for presence.

Grpc generated code in java gives you methods such as .hasEmail() which returns true if the value is present. The getter on an unset value will still return you the zero value. I think the golang version uses pointers that you can test for nil instead of an explicit hasX() method.

More info / discussion in this github issue

huangapple
  • 本文由 发表于 2017年9月6日 01:54:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/46060765.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定