V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
byqtxdy07
V2EX  ›  程序员

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

  •  
  •   byqtxdy07 · 300 天前 · 1146 次点击
    这是一个创建于 300 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

    你看这个文档,按文档中的意思,V2 版本并不需要标记为 optional 就有 has 方法,V3 只有标记为 optional 的才有 has 方法,这好像和有些搜索结果说的不一样啊
    sujin190
        8
    sujin190  
       300 天前
    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
        9
    byqtxdy07  
    OP
       300 天前
    @sujin190 ok ,谢谢大佬,我晚点试试
    byqtxdy07
        10
    byqtxdy07  
    OP
       299 天前
    @sujin190 解决了解决了,谢谢大佬 😙😙😙
    Aoang
        11
    Aoang  
       299 天前
    buf.build + connectrpc 省事很多
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2724 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 15:23 · PVG 23:23 · LAX 07:23 · JFK 10:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.