Java Protobuf (ver. 2.4.1) 和 Protobuf-net (ver. r480) 继承兼容性

Posted

技术标签:

【中文标题】Java Protobuf (ver. 2.4.1) 和 Protobuf-net (ver. r480) 继承兼容性【英文标题】:Java Protobuf (ver. 2.4.1) and Protobuf-net (ver. r480) inheritance compatibility 【发布时间】:2012-05-20 19:25:27 【问题描述】:

是否可以使用 Java Protobuf 反序列化以下使用 Protobuf-net 序列化的 DerivedMessage?

namespace Test.Protobuf

  [ProtoBuf.ProtoContract]
  [ProtoBuf.ProtoInclude(2550, "Test.Protobuf.DerivedMessage")]
  class BaseMessage
  
    [ProtoBuf.ProtoMember(1)]
    public string MessageId  get; set; 

    [ProtoBuf.ProtoMember(2)]
    public int CommandId  get; set; 
  

  [ProtoBuf.ProtoContract]
  class DerivedMessage : BaseMessage
  
    [ProtoBuf.ProtoMember(1)]
    public int ClientId  get; set; 

    [ProtoBuf.ProtoMember(2)]
    public string Message  get; set; 

    [ProtoBuf.ProtoMember(3)]
    public string Description  get; set; 
  

DerivedMessage 扩展 BaseMessage,阅读文档解决方案似乎是在 proto 文件中使用嵌套消息 但它不起作用,这是我的原型文件:

package protobuf;

option java_package = "test.protobuf";
option java_outer_classname = "Proto";

message BaseMessage 
    optional string message_id = 1;
    optional int32 command_id = 2;


message DerivedMessage 
    optional int32 client_id = 1;
    optional string token = 2;
    optional string message = 3;
    optional string description = 4;
    optional BaseMessage base_message = 5;

有解决办法吗?

谢谢

【问题讨论】:

【参考方案1】:

派生类是否可能不应该也有一个与父类具有相同 ID 的字段?在您的示例中,messageId 和 clientId 都具有相同的标识符:1.

【讨论】:

不,这根本不是问题【参考方案2】:

字段编号必须匹配,并且进入 BaseMessage,而不是 DerivedMessage。

在不相关的新闻中,您在 DerivedMessage 中的其他字段看起来很无聊; "token" 来自数字,后面的 2 个字段是一对一的。

message BaseMessage 
    optional string message_id = 1;
    optional int32 command_id = 2;
    optional DerivedMessage derived_message = 2550;


message DerivedMessage 
    optional int32 client_id = 1;
    optional string message = 2;
    optional string description = 3;

【讨论】:

嗨,马克,按照你的指示,我现在可以反序列化由 Protobuf-net 序列化的消息。现在的问题是 Protobuf-net 无法反序列化由 Java Protobuf 序列化的消息,它会抛出“无法将类型为 'Test.Protobuf.BaseMessage' 的对象转换为类型 'Test.Protobuf.DerivedMessage'”。例外。问题似乎是写入字节的顺序。实际上设置 ClientId = 3, CommandId = 5 Protobuf-net 序列化 b2 9f 01 02 08 03 10 05 而不是 Java Protobuf 序列化 10 05 b2 9f 01 02 08 03 不幸的是我无法更改 .Net 端类。 @user1406564 v2,对吧?烦人的 v1 解决了这个问题(尽管效率略低)。不可否认,这是 protobuf-net 的失败;它应该(并且确实)接受无序的伪继承。我可以尝试解决这个问题,但这不会是即时的。不幸的是,protobuf 根本不支持继承根本,对于 protobuf-net 实现必须有点厚颜无耻。我怪我。

以上是关于Java Protobuf (ver. 2.4.1) 和 Protobuf-net (ver. r480) 继承兼容性的主要内容,如果未能解决你的问题,请参考以下文章

使用带蜂巢的大象鸟来读取 protobuf 数据

ndk编译protobuf精简版(lite版)

Java中使用Protobuf

Mac安装Protobuf编译Java

Protobuf 实例(java)

在 Java 中读取 protobuf 消息时出现异常