首页 > 解决方案 > 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\x0anodejs序列化之间的主要区别是字节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文档,仍然找不到解决方案。有没有人遇到过同样的问题?

标签: pythonnode.jsprotocol-buffers

解决方案


在传递序列化的 blob 时,您似乎遇到了某种 UTF-8 编码问题。原始序列化字节(来自 Python)中有一个字节0xDE,但您引用的 node.js 版本却有0xC3 0x9E,它是 Unicode 代码点 U+00DE 的 UTF-8 编码。

我建议您使用 ASCII 安全编码(例如 base64)来传递 blob 以进行调试,只是为了安全起见。一旦成功,您可以确保以二进制模式打开所有相关文件和流。


推荐阅读