Reputation: 2730
I'm using proto3 with grpc, and I'm looking at a more efficient way of creating a protobuf message without using a builder and populating it.
If I have a string (from Message.toString()), can I recreate the message with the string?
If I have a message type
message TestMessage {
bool status = 1;
uint64 created = 2;
TestNested submessage = 3;
message TestNested {
int32 messageNumber = 1;
Entry entry = 2;
}
message Entry {
int32 id = 1;
EntryType entryType = 2;
}
enum EntryType {
DEFAULT_ENTRY = 0;
OTHER_ENTRY = 1;
}
}
and the below output:
status: true
created: 1534240073415
submessage {
messageNumber: 3
entry{
id: 47957
entryType: DEFAULT_ENTRY
}
}
How can I create the TestMessage? I've looked at the JavaDoc to see if there's a parseFrom()
method that takes in a string, but I'm not winning.
Upvotes: 9
Views: 21575
Reputation: 11
Below code snippet / client codes for various cases conversions between 'plain test format' to proto values. Most of the things are obvious in the protobuf documentation.
Proto file: phonemetadatabrokerproto.proto
message CastAroundCriteria {
optional string region_code = 1;
optional int32 prefix = 2;
}
public static void main(String args[]) {
// Creating a value object in program through proto APIs.
Phonemetadatabrokerproto.CastAroundCriteria cacb = Phonemetadatabrokerproto.CastAroundCriteria.newBuilder().setRegionCode("AE").setPrefix(20).build();
System.out.println(cacb);
// To travel over the wire as Byte string. Not in plain text, so not using special TextFormat kind of APIs. You have many other alternatives, please serach.
Phonemetadatabrokerproto.CastAroundCriteria cacb2 = null;
try{
cacb2 = Phonemetadatabrokerproto.CastAroundCriteria.parseFrom(cacb.toByteString());
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
System.out.println(cacb2);
// When vanilla string literals has to be passed between the APIs / on wire. Using TextFormat APIs
CharSequence inputCS = cacb.toString();
Phonemetadatabrokerproto.CastAroundCriteria.Builder cacb3 = null;
try{
cacb3 = Phonemetadatabrokerproto.CastAroundCriteria.newBuilder();
TextFormat.getParser().merge(inputCS, cacb3);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(cacb3);
// Hardcoded string unmarshalling to proto.
CharSequence rawInput = "region_code: \"AE\" prefix: 20";
Phonemetadatabrokerproto.CastAroundCriteria.Builder cacb4 = null;
try{
cacb4 = Phonemetadatabrokerproto.CastAroundCriteria.newBuilder();
TextFormat.getParser().merge(rawInput, cacb4);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(cacb4);
// Dynamic commandline input has to be string literal "region_code: 'AE' prefix: 20" when running in linux. Otherwise we need to escape \" in
// command input. More of bash is culprit. :)
CharSequence cmdInput = args[0];
Phonemetadatabrokerproto.CastAroundCriteria.Builder cacb5 = null;
try{
cacb5 = Phonemetadatabrokerproto.CastAroundCriteria.newBuilder();
TextFormat.getParser().merge(cmdInput, cacb5);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(cacb5);
}
Please ignore some of the naming conventions, like class name is Phonemetadatabrokerproto and also exception handling.
Upvotes: 1
Reputation: 2730
I was looking for the TextFormat parser. The format that Message.toString()
prints is the TextFormat representation.
To convert back to a protobuf message, I did the below:
TestMessage testMessage = new TestMessage.newBuilder();
CharSequence myText = "status: true\n ...";
com.google.protobuf.TextFormat.getParser().merge(myText, testMessage);
Upvotes: 12