1

Is it possible with Java Protobuf deserialize the following DerivedMessage serialized with Protobuf-net?

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 extends BaseMessage, reading documentation the solution seems to be using nested messages in proto files but it doesn't work, here my proto file:

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;
}

Is there a solutions?

Thank you

user1406564
  • 91
  • 1
  • 6

2 Answers2

0

The field-number must match, and goes in BaseMessage, not DerivedMessage.

In unrelated news, your other fields in DerivedMessage look borked; "token" has come from number, and 2 later fields are off-by-one.

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;
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Hi Mark, following your instructions I can now deserialize messages serialized by Protobuf-net. The problem now is that Protobuf-net can not deserialize messages serialized by Java Protobuf, it throws an "Unable to cast object of type 'Test.Protobuf.BaseMessage' to type 'Test.Protobuf.DerivedMessage'." exception. The problem seems to be the order on which bytes are written. In fact settings ClientId = 3, CommandId = 5 Protobuf-net serilizes b2 9f 01 02 08 03 10 05 instead Java Protobuf serilizes 10 05 b2 9f 01 02 08 03 Unfortunately I can not change the .Net side classes. – user1406564 May 21 '12 at 15:40
  • @user1406564 v2, right? Annoyingly v1 copes with that (although slightly inefficiently). This is undeniably a failing in protobuf-net; it should (and did) accept pseudo-inheritance out-of-order. I can try to fix that, but it won't be instant. Unfortunately, protobuf simply doesn't support inheritance *at all*, to the protobuf-net implementation has to be a bit cheeky. I blame me. – Marc Gravell May 21 '12 at 17:24
0

Is it possible that the derived class should not also have a field with the same ID as the parent class? In your example, both messageId and clientId have the same identifier: 1.

Manish
  • 1,726
  • 3
  • 23
  • 29