踩到 Protobuf 解析坑了,如何才能严格解析 Protobuf? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
tool2d
V2EX    程序员

踩到 Protobuf 解析坑了,如何才能严格解析 Protobuf?

  •  
  •   tool2d 2023-09-21 18:03:17 +08:00 3071 次点击
    这是一个创建于 819 天前的主题,其中的信息可能已经有所发展或是发生改变。
    解析是指 protobuf 二进制文件。这协议和 json 不一样,数据类型并不是 1 对 1 的。

    比如一个 Length-delimited 类型,int 是 2 ,同时对应多个子类型。可以是嵌入式 messages ,可以是 utf8 文本字符串,也可以是纯 bytes 数组。

    现在写了一个解析器,是什么类型,要纯粹靠猜。先尝试 utf8 ,不行再退回到嵌入式 messages ,解析一次。如果还是不行,就默认为 bytes 数组。

    总觉得很不靠谱的样子,在没有 proto 辅助的前提下,如何才能优雅的转为 json?
    22 条回复    2023-09-22 10:39:09 +08:00
    AoEiuV020JP
        1
    AoEiuV020JP  
       2023-09-21 18:10:42 +08:00
    在用 protobuf ,这玩意儿难道不是自动生成序列化和反序列化代码然后再也不改的?
    还是你解析的是别人的 protobuf 消息不知道真实格式?这当然只能猜了,多整点数据排除所有错误答案才能得出结果,
    tool2d
        2
    tool2d  
    OP
       2023-09-21 18:19:06 +08:00
    @AoEiuV020JP 我在用微软 ai 推理模型,用的是 protobuf 格式。

    pb 本身是序列化格式没错,但是大部分模型推导的结构都比较松散,而且 onnx 里面的 layers 复杂度比较高。会夹杂各种没遇到过的 operators 。用库不太方便,一些 OP 会变。

    复杂度一高,代码就会变复杂。就希望能写一个稍微通用一点的转换工具了,化简 AI 推导流程。
    stamhe
        3
    stamhe  
       2023-09-21 18:19:23 +08:00
    proto 本身就会定义数据类型啊。。。还有不知道的?
    tool2d
        4
    tool2d  
    OP
       2023-09-21 18:22:15 +08:00
    @stamhe AI 模型和通讯协议不一样,并没有 proto 文本数据。

    就只给一个模型 pb 二进制文件,我要反推内部的输入参数,把 input/output 对接上才行。

    每个模型权重输入,每个版本都不太一样。
    pkoukk
        5
    pkoukk  
       2023-09-21 18:22:19 +08:00   1
    我以为你在吐槽隔壁那个帖子,没想到你是认真的
    thinkershare
        6
    thinkershare  
       2023-09-21 18:28:45 +08:00
    @tool2d proto 不是自包含和自解释协议,因此你的想法不对。
    tool2d
        7
    tool2d  
    OP
       2023-09-21 18:33:21 +08:00
    @thinkershare 这个开源工具可以解析任意 proto 生成的二进制文件,不需要原始格式

    https://protobuf-decoder.netlify.app/

    这工具用起来没问题,但是我去看源代码实现方式,核心功能是依靠 try catch 实现的,说白了就是靠猜,这就很尴尬了。
    sujin190
        8
    sujin190  
       2023-09-21 18:36:46 +08:00 via Android   4
    预定义格式不是自解析的不靠猜靠啥,不知道你在无厘头吐槽啥
    thinkershare
        9
    thinkershare  
       2023-09-21 18:38:28 +08:00
    @tool2d protobuf 的官网已经明确说明,没有 proto 的原始定义下,如果要实现子描述,你需要自己实现。
    tool2d
        10
    tool2d  
    OP
       2023-09-21 18:40:10 +08:00
    @sujin190 当年 google 发明 protobuf 的时候,如果想弄成 json 这种自解析,就是举手之劳。但就是偏不,我想吐槽这一点。

    把文本和 messages 分开有那么难嘛,不就是一个 byte 类型,就能解决的事情。
    billlee
        11
    billlee  
       2023-09-21 19:06:09 +08:00 via Android
    @tool2d 发明 protobuf 就是为了不自解析,已经有 json 和 xml 了,为什么要重新造轮子呢
    lasuar
        12
    lasuar  
       2023-09-21 19:07:45 +08:00
    lightweight, compact
    seakingii
        13
    seakingii  
       2023-09-21 19:11:03 +08:00
    还自解析....你太自以为是了吧
    PB 尽量的压缩数据,做自解析不是和目标相勃了
    changnet
        14
    changnet  
       2023-09-21 19:19:22 +08:00
    @tool2d 你这说法就怪了
    当初之所以弄一个 protobuf 出来,就是因数 json 是自解析的,包含了太多数据,导致编码后的数据太大,效率也不高,才做出来的。

    假如做成和 json 一样,那为什么不直接用 json 。或者,你想找的是 bson ,而不是 protobuf 。

    为什么非要按 json 的方式去使用 protobuf ,他们本来就不是一样的东西。想吃青菜就买青菜,而不是买了个萝卜,再想这萝卜的味道为什么和青菜不一样。
    duke807
        15
    duke807  
       2023-09-21 19:27:45 +08:00 via Android
    @tool2d

    你需要的是用 msgpack 代替 json
    exch4nge
        16
    exch4nge  
       2023-09-21 19:49:09 +08:00   1
    可以用 protoc --decode_raw 解析任意二进制到 protobuf 的 text format ,没 proto ,最多只能到这个程度。
    lsry
        17
    lsry  
       2023-09-21 20:00:22 +08:00   1
    /t/975214
    模仿是吧
    bianhui
        18
    bianhui  
       2023-09-22 08:39:15 +08:00
    没理解,为啥要自己写?现成的不能用吗?第二,为啥要自解析,你想转 json ,那你就先转为程序的对象,在序列化为 json 呗。为啥不要 proto ,你是爬取别的数据吗?获取不到别人的 proto 吗?
    sujin190
        19
    sujin190  
       2023-09-22 08:51:57 +08:00 via Android
    @tool2d 发明 protobuf 本来就是为了解决现有压缩率和性能不足的问题,否则文本型有 json ,二进制型有 msgpack ,为啥要再造一个,再说选 protobuf 的场景本来就是看重其编码效率、压缩率和兼容性方案,你居然偏偏吐槽 protobuf 之所以被选择有优势的地方设计的不行
    sujin190
        20
    sujin190  
       2023-09-22 09:09:27 +08:00 via Android
    @tool2d 而且顺便说,protobuf 之所以能在数据库,分布式系统和 AI 学习场景中得到广泛应用。很大程度就是因为你吐槽设计不行的预定义格式不自解析,可靠而稳定的数据结构才能保证这些系统的可靠性与准确性,不自解析预定义格式又有良好兼容性才是 protobuf 设计的好的地方
    ggvoking
        21
    ggvoking  
       2023-09-22 10:07:12 +08:00
    建议先了解一下 protobuf 原理,类型本来就是固定的,要实现定义好,tlv 格式,读到 tag 就知道是对应的什么类型了。你想 pb 转 json 的话,首先要有数据文件,然后还需要
    1. proto 生成的类自定义代码类文件,这样这个类包含 tag 和类型,然后走反射转 json 。
    2. 有 proto 文件,可以不生成代码,可以直接走 proto 反射,golang 就有反射库[protoreflect]<https://github.com/jhump/protoreflect> ,其他语言自己找
    isFire
        22
    isFire  
       2023-09-22 10:39:09 +08:00
    难搞,之前做过动态解析 protobuf 格式数据的功能,方法可以参考一下,要解析最好还是先拿到 Message ,然后识别每个字段的顺序和类型,然后依次解析
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2897 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 14:11 PVG 22:11 LAX 06:11 JFK 09:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86