9

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.

4
  • protobuf on java has support for binary (protobuf) data, or JSON data; that data is neither... Are you sure that is a supported format for parsing (I'm not)? Commented Sep 3, 2018 at 14:04
  • I don't know, but it's what the Protobuf Java code outputs when you toString() it. Do you know how to output a JSON format? Because then I could use that instead of the above format. Commented Sep 3, 2018 at 14:08
  • sorry, you'd have to look it up... I've never had much interest in JSON via protobuf, so I've never used it... if I wanted JSON I'd use a JSON serializer :) Commented Sep 3, 2018 at 14:09
  • 1
    Is it here? stackoverflow.com/questions/28890646/… Commented Sep 3, 2018 at 14:10

2 Answers 2

12

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);
Sign up to request clarification or add additional context in comments.

1 Comment

This is not working for kotlin, any clue for kotlin?
1

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.

Comments

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.