python - python和nodejs之间使用protobuf的序列化问题
问题描述
在 python 和 nodejs 之间序列化 protobuf 消息时出现兼容问题。我有一条如下所示的 protobuf 消息:
message User {
reserved 2,3;
string user_id = 1;
int32 coin = 4;
int32 exp = 5;
int32 gem = 6;
int32 level = 7;
}
我想序列化一个消息实例,如:
"userId": "3562957934"
"coin": 350
"exp": 1
"gem": 30
"level": 1
当我做 user_pb2.User.SerializeToString()
\x0a\x0a\x33\x35\x36\x32\x39\x35\x37\x39\x33\x34\x20\xde\x02\x28\x01\x30\x1e\x38\x01
或二进制
1101 1110 0000 0010 0010 1000 0000 0001 0011 0000 0001 1110 0011 1000 0000 0001
当我尝试在 nodejs 中反序列化此消息时,我得到
"userId": "3562957934"
"coin": 381
"exp": 1
"gem": 30
"level": 1
有错误的“硬币”价值
然后我尝试创建一个消息实例(硬币值= 350)并在nodejs中反序列化它。我得到一个不同的二进制文件:
\x5c\x0a\x5c\x0a\x33\x35\x36\x32\x39\x35\x37\x39\x33\x34\x20\xc3\x9e\x02\x28\x01\x30\x1e\x38\x01
或二进制:
1100 0011 1001 1110 0000 0010 0010 1000 0000 0001 0011 0000 0001 1110 0011 1000 0000 0001
我发现除了头部的奇怪字节之外, python\x0a\x0a
和\x5c\x0a\x5c\x0a
nodejs序列化之间的主要区别是字节1101 1110
(python)vs 1100 0011 1001 1110
(nodejs),或者字符串形式3562957934 �(08
(python)vs 3562957934 Þ(08
(nodejs)
我的协议是:
/usr/local/bin/protoc -I=protos user.proto --python_out=pb
(python)
/usr/local/bin/protoc --js_out=import_style=commonjs,binary:protos user.proto -I=protos
(nodejs)
我想给定相同的消息,python 和 nodejs 的序列化应该是相同的,不是吗?我尝试搜索google官方protobuf文档,仍然找不到解决方案。有没有人遇到过同样的问题?
解决方案
在传递序列化的 blob 时,您似乎遇到了某种 UTF-8 编码问题。原始序列化字节(来自 Python)中有一个字节0xDE
,但您引用的 node.js 版本却有0xC3 0x9E
,它是 Unicode 代码点 U+00DE 的 UTF-8 编码。
我建议您使用 ASCII 安全编码(例如 base64)来传递 blob 以进行调试,只是为了安全起见。一旦成功,您可以确保以二进制模式打开所有相关文件和流。
推荐阅读
- javascript - 如何使用 JavaScript 检索同样在 JavaScript 中创建的 html 元素
- python - python36-devel 与 python3-dev
- python - 允许 RabbitMQ 和 Pika 保持连接始终打开
- npm - 我在哪里可以找到所有 npm 标志/标签/选项的列表?
- python - compile() 缺少 1 个必需的位置参数:'loss'
- excel - Excel 公式:COUNTIFS() 返回值错误
- elasticsearch - 在 ElasticSearch 中启用自动完成查询
- flutter - 在使用 flutter_bloc 库调度事件之前等待一些结果
- tensorflow - Kubeflow 中的分布式张量流 - NotFoundError
- vue.js - Vue路由器中的基本选项