Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know which protobuf message the byte array is?

I want to use protobuf instead of Json to communicate between message queue.

I know how to deal with it when there is only one proto message.

Assume that the proto file is:

//person.proto
syntax = "proto3";

option java_outer_classname = "PersonProto";

message Person {
    int32 id = 2;
    string name = 1;
    string email = 3;
}

Now, i can deal with it with the approach below:

PersonProto.Person person = PersonProto.Person.newBuilder()
        .setEmail("[email protected]")
        .setId(1)
        .setName("name-test")
        .build();

byte[] bytes = person.toByteArray();

//Transfer from publisher to consumer between message queue.

//I can deserialise it, because i know the proto message is Person.
PersonProto.Person.parseFrom(bytes);

But what if there are multiple proto messages?

Assume that there is another proto message called Address.

syntax = "proto3";

option java_outer_classname = "PersonProto";

message Person {
    int32 id = 2;
    string name = 1;
    string email = 3;
}

message Address {
    string address = 1;
}

When consumer received byte array from message queue, how to know which proto message it is? and how to deserialise the byte array?

like image 588
Xu Yao Avatar asked Nov 06 '16 14:11

Xu Yao


People also ask

Is protobuf text or binary?

Protobuf is a binary format, so reading and writing should be done as binary, not text. If you don't want binary format, you should consider using something other than protobuf (there are lots of textual data formats, such as XML, JSON, CSV); just using text abstractions is not enough.

What is a message in protobuf?

namespace google::protobuf. Defines Message, the abstract interface implemented by non-lite protocol message objects. Although it's possible to implement this interface manually, most users will use the protocol compiler to generate implementations.

Does order matter in protobuf?

The textual order is largely irrelevant, although it may impact some code generation tooling - but most languages don't care about declaration order, so even that: won't matter.


1 Answers

Protobuf 3 introduced the concept of Any that can act in a similar way to the top-level-message pattern explained by @AdamCozzette.

On the write-side you pack your message in an Any:

Person person = ...
Any any = Any.pack(person);

out.write(any.toByteArray());

Then on the read-side you read into an Any and switch on the types you are interested in:

Any any = Any.parseFrom(in);

if (any.is(Person.class)
{
  Person person = any.unpack(Person.class);
  ...
}
else if (any.is(Address.class);
{
  Address address = any.unpack(Address.class);
  ...
}
else
{
  //Handle unknown message
}

Using Any removes the need for special a message type (the top-level-message), but also removes an element of type-safety in as much as you may receive messages that the consuming code does not know how to handle.

like image 59
Nick Holt Avatar answered Oct 10 '22 15:10

Nick Holt