ts 使用 grpc ts-proto 的一点问题

2024-01-26 15:36:05 +08:00
byqtxdy07  byqtxdy07

我在 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

求大佬们帮小弟看看这两个问题😙😙😙

1248 次点击
所在节点   程序员  程序员
11 条回复
sujin190
sujin190
2024-01-26 15:42:27 +08:00
生成的结构还有个 hasTitle 的属性吧,你看看,客户端不给 title 赋值的时候服务端接收解码这个属性返回的就是 false ,null 值不标准,需要额外信息传递不说可能有的语言无法正确处理 null 语义
XCFOX
XCFOX
2024-01-26 15:53:06 +08:00
只能说 TypeScript 领先太多了。grpc 是带着 C/C++、Go 的包袱设计的。在 Go 中不传值就是零值,根本没办法区分 undefined 和空字符串。
能用 json 还是用 json 吧,根本不差 protobuf 那点性能。如果是服务间通讯的话试试 nats 消息中间件,实测延迟比 grpc 低,速度比 grpc 快。
byqtxdy07
byqtxdy07
2024-01-26 15:57:17 +08:00
@sujin190 !我看了一眼,直接生成的 ts 代码和 java 代码都没有显式的 hasTitle 属性,java 这边 request 请求体中倒是有一个 hasField 的 api
byqtxdy07
byqtxdy07
2024-01-26 16:00:34 +08:00
@XCFOX 不行的话雀氏要转回 json 了😂
byqtxdy07
byqtxdy07
2024-01-26 16:11:18 +08:00
@sujin190 试了一下,好像 proto2 中是有这个 hasTitle 的设置的,但 proto3 就没有了,不知道按下面这样写能不能用:
request.hasField(ArticleProto.ArticleCreateReq.getDescriptor().findFieldByName("title"));
但不是很方便,硬编码是一方面,再加一个属性多的话写起来也有点麻烦
AloneHero
AloneHero
2024-01-26 16:17:40 +08:00
Proto2 默认值应该是挂载在原型链上的,如果是主动传递的值则在实例上。不知道 proto3 改变没有,应该没改
sujin190
sujin190
2024-01-26 17:07:52 +08:00
@byqtxdy07 #5 我们用的也是 proto3 啊,optional 标记的字段就有 has 相关属性。。你这啥毛病

https://protobuf.dev/programming-guides/field_presence/

你看这个文档,按文档中的意思,V2 版本并不需要标记为 optional 就有 has 方法,V3 只有标记为 optional 的才有 has 方法,这好像和有些搜索结果说的不一样啊
sujin190
sujin190
2024-01-26 17:13:35 +08:00
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 的吧
byqtxdy07
byqtxdy07
2024-01-26 17:53:03 +08:00
@sujin190 ok ,谢谢大佬,我晚点试试
byqtxdy07
byqtxdy07
2024-01-27 10:20:04 +08:00
@sujin190 解决了解决了,谢谢大佬 😙😙😙
Aoang
Aoang
2024-01-27 10:59:53 +08:00
buf.build + connectrpc 省事很多

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1011830

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX