c# - 为什么在使用 java 和 protobuf-net 的 Protocol Buffer 进行序列化时 byte[] 不同?

标签 c# java protocol-buffers zeromq protobuf-net

当我在 Java 中使用 Protocol Buffer 序列化这个对象时,我得到这个字节数组:

byte[] topic = Transport.newBuilder()
            .setTopic(Topics.ORD)
            .setExtension(Ord.command, Commands.INSERT)
            .build()
            .toByteArray();

// [8,2,16,0]

当我对 protobuf-net 做同样的事情时,我得到了这个

var transport = new Transport
{
    topic = Topics.ORD,
    command = Commands.INSERT
};

var stream = new MemoryStream();
Serializer.Serialize(stream, transport);
byte[] result = stream.ToArray(); // [8,2]

这在使用 zmq 和基于 bye 数组的订阅时给我带来了一些麻烦。 我如何确保两个数组看起来相同?

最佳答案

protobuf-net 在 v1 中做出了“零默认”假设。如果我从头开始,我可能不会再做出决定,而且确实可以在 v2 中禁用此行为。但就目前而言,在许多情况下,它假定零作为隐式默认值。我猜你的 command 是一个不可为 null 的枚举,在这种情况下它将应用这个逻辑(作为旁注:如果它是 nullable,它会这样做 - 它会使用 null 检查包含/排除决定)。

因此,它决定第二个字段(字段编号 2,编码为 varint)不需要序列化。因此没有 [16, 0]

选项:

  • 使用一个可空成员(等同于optional)——即public SomeEnum?命令 {get;set;}
  • 将成员标记为必需(ProtoMemberAttribute 上的IsRequired=true)
  • 关闭隐式零默认行为(RuntimeTypeModel 实例上的UseImplicitZeroDefaults)

关于c# - 为什么在使用 java 和 protobuf-net 的 Protocol Buffer 进行序列化时 byte[] 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21550677/

相关文章:

java - 在 JFreeChart XYPLot 中改变单点的形状

java - 如何让 Graphics.drawString 从边界底部绘制?

python - 如何使用 Python 和 Google 的 Protocol Buffer 来反序列化通过 TCP 发送的数据

c++ - 如何使用 ProtoBuf 扩展在 C++ 中获得多态性

c# - 了解 Parallel.For 循环和局部变量

javascript - ExtJs 编辑器中的多行文本区域

java - StringTemplate 为给定模板定义的属性列表

c++ - 如何使用 union 类型 Protobuf C++

c# - 设计器 resx 文件仍然为空

c# - 在 streamwriter 、 streamreader 之前使用 using 语句的好处/使用