Java:将字符串转换为protobuf

9
我正在使用proto3和grpc,我正在寻找一种更有效的方法来创建protobuf消息,而不使用构建器并填充它。
如果我有一个字符串(来自Message.toString()),我可以使用该字符串重新创建消息吗?
如果我有一个消息类型。
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;
    }
}

以下是输出结果:

status: true
created: 1534240073415
submessage {
  messageNumber: 3
  entry{
    id: 47957
    entryType: DEFAULT_ENTRY
  }
}

我该如何创建TestMessage?我查看了JavaDoc,看看是否有一个接受字符串的parseFrom()方法,但我没有找到。


Java上的protobuf支持二进制(protobuf)数据或JSON数据;但是这些数据都不是...你确定这是一种受支持的解析格式吗?(我不确定) - Marc Gravell
我不知道,但这是Protobuf Java代码在toString()时输出的内容。你知道如何输出JSON格式吗?因为那样我可以使用它来代替上述格式。 - nevi_me
抱歉,你得自己查一下...我对通过protobuf使用JSON没有太大兴趣,所以从未使用过...如果我需要JSON,我会使用JSON序列化器 :) - Marc Gravell
1
这是吗?https://dev59.com/xl4b5IYBdhLWcg3wnS0e - kan
2个回答

10

我正在寻找文本格式解析器。 Message.toString()打印的格式是TextFormat表示。

要转换回protobuf消息,我执行了以下操作:

TestMessage testMessage = new TestMessage.newBuilder();

CharSequence myText = "status: true\n ...";

com.google.protobuf.TextFormat.getParser().merge(myText, testMessage);

这对Kotlin不起作用,有关于Kotlin的线索吗? - Arth Tilva

1
以下是用于各种情况下将“纯文本格式”转换为Proto值的代码片段/客户端代码。大部分内容在protobuf文档中都很明显。
Proto文件: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);
  }

请忽略一些命名约定,例如类名为Phonemetadatabrokerproto以及异常处理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接