我在 proto 文件中定义了一个 message
message ArticleUpdateReq {
optional string title = 3;
}
当我通过 ts-proto 生成的代码作为客户端发送请求时发现:即使我客户端不传递 title 字段,在服务端接收数据的时候 title 也会有一个空字符串的默认值 "",这导致了我无法判断用户是删除了 title ,还是没有修改 title(用的 java mp ,原本是传的 null 的话就视为没有修改,传 "" 就视为删除)
我查阅了下资料,说可以写成
message ArticleUpdateReq {
optional google.protobuf.StringValue title = 3;
}
我看了一下生成的 java 服务端生成的代码,雀氏没有默认值""了,但又出现了一个新的问题:
ts-proto 生成新的代码并发送请求报错了:
Request message serialization failure: .article.ArticleUpdateReq.title: object expected
求大佬们帮小弟看看这两个问题😙😙😙
1
sujin190 286 天前
生成的结构还有个 hasTitle 的属性吧,你看看,客户端不给 title 赋值的时候服务端接收解码这个属性返回的就是 false ,null 值不标准,需要额外信息传递不说可能有的语言无法正确处理 null 语义
|
2
XCFOX 286 天前
只能说 TypeScript 领先太多了。grpc 是带着 C/C++、Go 的包袱设计的。在 Go 中不传值就是零值,根本没办法区分 undefined 和空字符串。
能用 json 还是用 json 吧,根本不差 protobuf 那点性能。如果是服务间通讯的话试试 nats 消息中间件,实测延迟比 grpc 低,速度比 grpc 快。 |
3
byqtxdy07 OP @sujin190 !我看了一眼,直接生成的 ts 代码和 java 代码都没有显式的 hasTitle 属性,java 这边 request 请求体中倒是有一个 hasField 的 api
|
5
byqtxdy07 OP @sujin190 试了一下,好像 proto2 中是有这个 hasTitle 的设置的,但 proto3 就没有了,不知道按下面这样写能不能用:
request.hasField(ArticleProto.ArticleCreateReq.getDescriptor().findFieldByName("title")); 但不是很方便,硬编码是一方面,再加一个属性多的话写起来也有点麻烦 |
6
AloneHero 286 天前 via Android
Proto2 默认值应该是挂载在原型链上的,如果是主动传递的值则在实例上。不知道 proto3 改变没有,应该没改
|
7
sujin190 286 天前
@byqtxdy07 #5 我们用的也是 proto3 啊,optional 标记的字段就有 has 相关属性。。你这啥毛病
https://protobuf.dev/programming-guides/field_presence/ 你看这个文档,按文档中的意思,V2 版本并不需要标记为 optional 就有 has 方法,V3 只有标记为 optional 的才有 has 方法,这好像和有些搜索结果说的不一样啊 |
8
sujin190 286 天前
How to Enable Explicit Presence in Proto3
These are the general steps to use field tracking support for proto3: Add an optional field to a .proto file. Run protoc (at least v3.15, or v3.12 using --experimental_allow_proto3_optional flag). Use the generated “hazzer” methods and “clear” methods in application code, instead of comparing or setting default values @byqtxdy07 #5 好吧,你看后面一段,这个规则需要在 3.15 版本以上才有,3.12 以上需要用 --experimental_allow_proto3_optional 来开启,其它版本应该就是搜索的结果一样不支持,我们用的 3.17 所以正常了,需要的话升级以下呗,grpc 应该兼容新版本的 protobuf 的吧 |