5

Consider that I have byte array - byte[] which represent some kind of serialized protobuf object. Is there any way to print it to output, something like

1: 123
2: Jhon
3: Doe
4: 0

Where 1 is int field, 2 and 3 are strings and 4 is boolen

TextFormat.print requires me to provide concrete Builder of protobuf object, which I do not know.

0

2 Answers 2

4

Define a type EmptyMessage like:

message EmptyMessage {
  // nothing
}

Now parse your message as EmptyMessage, then call toString() on it.

Why does this work? Well, consider that it is backwards-compatible to add fields to a message type. When you add a field, then send a message using that field to an old program that wasn't build with knowledge of the field, then the field is treated as as "unknown field". Unknown fields are printed as number / value pairs. Now, if you start with EmptyMessage and add fields, you can obviously get any other message. Therefore, all message types are "backwards-compatible" with EmptyMessage. Therefore, any message can be parsed as EmptyMessage to treat all the fields as unknown fields.

Sign up to request clarification or add additional context in comments.

3 Comments

Any idea how to do it without declaring empty msg in proto ? I mean dynamically at Runtime ?
@user12384512 Sorry, I don't understand. The same EmptyMessage will work for all types, so why would you need to define it "dynamically at runtime"? Why can't you define EmptyMessage at the same time as you are writing the other code for this feature? That said, if you really insist on doing it "dynamically at runtime", you can use DynamicMessage -- but this will be way more work and have no advantages.
Caveat: if the protobuf represents an message that contains a sub-message, the sub-message will be stringified as a byte array; in other words, the sub-message will not be unserialized.
1

if we can make the assumption that the fields are all primitive types (i.e. not sub-messages) then you should be able to loop through all the fields very simply -

for(Entry<FieldDescriptor, Object> entry : msg.getAllFields().entrySet())
{
    if(entry.getValue() != null)
        System.out.println(entry.getKey().getName() + ": " + entry.getValue().toString());
    else
    System.out.println(entry.getKey().toString() + ": null");
}

However, I am pretty sure that protobuf objects properly implement the toString() method, so I think you should be able to simply call

protoObj.toString()

to get a string representation of the protobuf object. For more info, take a look at: https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/GeneratedMessage.ExtendableMessage#getAllFields%28%29

3 Comments

I do not have message object as I mentioned above. I have byte array
using the google protobuf library, you should be able to construct the object with only the byte array. why parse it yourself when there are libraries made to do that already?
This original question was not about usage of protobuf library, it was about how to print message of unknown type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.