Nodejs 能动态解析 protobuf 么?

发布于 1周前 作者 vueper 来自 nodejs/Nestjs

Nodejs 能动态解析 protobuf 么?

使用 protobuf 的时候必须得先把.proto 文件定义好,但是很多时候需要解析的数据内容是不确定的,能动态解析么?

解析库用的是 protobuf.js

或者有更适合的库?

25 回复

动态解析会影响性能,如果不需要考虑性能的话直接用 json 之类的就行了……


谢谢。 先说说如何动态解析呢?

静态语言动态解析 json 也没那么简单吧

protobuf 有 any 跟 oneof。。。

要么 json,要么 https://avro.apache.org/ ,后者有类似于 pb 的版本升级要求。

缺信息,解不了





append 了下,麻烦再看看,谢谢!

你没有明白我的意思,动态解析和 protobuf 设计的初衷不符,所以官方的 protobuf 库都不会支持动态解析的
当然,可以自己做……但是我觉得不如直接用 json

嗯,大多数情况下确实先要定义好.proto,但是实际开发中还是有极个别会动态的来使用

protobuf 是向前兼容的啊,直接解析就好了啊。
虽然 nodejs 是动态语言,但是你为什么要用一个未定义的字段?

既然你解析的数据是 protobuf 格式,那么传给你数据的那一方不是肯定定义了.proto 文件吗,同步一下.proto 文件不就可以了,为什么还要自己写.proto 文件呢

通讯结构应该一早就定好,该怎么样就怎么样,不应该有变化的可能性,要么就是数据结构定义的不好。

嗯,理论上是这样的。 但是比如说某一个指令是获取用户背包里的数据的,背包里的数据以 json 的形式存在。不同的用户背包里的数据不一样,这样就牵涉到返回的数据格式有多有少。所以这里就在想能不能动态的解析和转化

背包数据种类也是有限的吧,全部以可选属性加上去不就行了?

谢谢,刚用这个不知道有可选属性?我找找文档

你需要的是’热更新’?

不是的,就是数据格式不是很确定

proto3 全部是可选,proto2 有 optional 关键字。一般情况下所有字段都应该是 optional 的,以上层约定是不是必选。

proto2 会写成这个样子:
message TextMessage {
optional int32 age = 1;
optional string name = 2; // Required.
}

另外 int32 写成 uint32 更好,如果你在 int32 里面存个-1 那会超级长的。用 uint32 的话可以用 has_age()来判断这个字段是不是存在。

这个是协议设计不合理问题

nodejs 还用什么 protobuf 嘛……

我们 c 艹的不得不用 protobuf 没办法,你们 nodejs 用是找虐啊……

nodejs 的 protobuf 坑很多,还会导致你 npm install 巨慢,建议谨慎使用。

对于 nodejs 来说动态解析静态解析性能差别不大
protobuf.js 是最好的了,没有之一,当然还有很多不足比如 OnceOf Any google.protobuf.中的 wellKnownType 不过都可以通过扩展 protobuf.js 轻松实现

protobuf 的初衷不是动态解析吧?

protobuf 的初衷应该是数据压缩吧,目前看是压缩率较高的一种方式。
有很多 JSON 与 protobuf 互转的 nodejs 库,可以直接使用。

是的,Node.js 可以动态解析 Protocol Buffers(protobuf)。Protocol Buffers 是一种由 Google 开发的语言中立、平台中立的可扩展机制,用于序列化结构化数据。在 Node.js 环境中,你可以使用 protobufjsgoogle-protobuf 库来动态解析 protobuf 数据。

以下是使用 protobufjs 动态解析 protobuf 的一个简单示例:

首先,安装 protobufjs

npm install protobufjs

然后,你可以使用以下代码动态解析 protobuf 数据:

const protobuf = require("protobufjs");

// 动态加载或定义 .proto 文件或 protobuf schema
const root = await protobuf.loadSync("path/to/your.proto");

// 获取消息类型
const MyMessage = root.lookupType("MyMessage");

// 假设你有一个 protobuf 编码的 Buffer
const buffer = Buffer.from(/* protobuf encoded data */);

// 解码
const message = MyMessage.decode(buffer);

console.log(message);

在这个例子中,你需要将 "path/to/your.proto" 替换为你的 .proto 文件的实际路径。MyMessage 是你在 .proto 文件中定义的消息类型。decode 方法用于将 protobuf 编码的 Buffer 解码为 JavaScript 对象。

注意,如果你使用的是 google-protobuf 库,过程会略有不同,但基本思想是相同的:加载 .proto 文件,获取消息类型,然后解码数据。选择哪个库取决于你的具体需求和偏好。

回到顶部