Question

When I serialize this object with protocol buffers in Java, I get this byte array:

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

// [8,2,16,0]

When I do the same with protobuf-net, I get this

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

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

This causes me some trouble when using zmq and a subscription based on the bye array. How can i make sure that both arrays will look the same?

Was it helpful?

Solution

protobuf-net, in v1, made a "zero defaults" assumption. Probably not a decision I would make again, if I was starting from scratch, and indeed this behaviour can be disabled in v2. But as it stands, in many cases it assumes zero as an implicit default. I'm guessing that your command is a non-nullable enum, in which case it will apply this logic (as a side-note: if it was nullable, it would not do this - it would use the null check for the include/exclude decision).

Because of this, it has decided that the second field (field number 2, encoded as varint) doesn't need to be serialized. Hence no [16, 0].

Options:

  • use a nullable member (equivalent to optional) - i.e. public SomeEnum? Command {get;set;}
  • mark the member as required (IsRequired=true on the ProtoMemberAttribute)
  • turn off implicit zero default behaviour (UseImplicitZeroDefaults on a RuntimeTypeModel instance)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top