Protobuf和Java:将对象放入其中

时间:2018-04-06 15:09:18

标签: java protocol-buffers

假设你有这个protobuf模型:

message ComplexKey {
    string name = 1;
    int32 domainId = 2;
}

message KeyMsg {
    oneof KeyMsgOneOf {
        string name = 1;
        ComplexKey complexName= 2;
    }
}

和一个对象obj,你知道它是一个字符串或一个ComplexKey。

问题

Whitout显式检查obj类类型,这是使用protobuf Java API将obj置于正确字段中构建新KeyMsg实例的最有效方法吗?

更新:如果protoc生成一个帮助方法来完成我需要的工作,那就太棒了。

UPDATE2:给出Mark G.下面的正确评论并假设所有字段的类型不同,到目前为止我找到的最佳解决方案是(简化版):

     List<FieldDescriptor> lfd = oneOfFieldDescriptor.getFields();
     for (FieldDescriptor fieldDescriptor : lfd) {
           if (fieldDescriptor.getDefaultValue().getClass() == oVal.getClass()) {
              vmVal = ValueMsg.newBuilder().setField(fieldDescriptor, oVal).build();
              break;
           }
     }

2 个答案:

答案 0 :(得分:1)

我怀疑有一种比使用instanceof更好的方式:

KeyMsg.Builder builder = KeyMsg.newBuilder();
if (obj instanceof String) {
  builder.setName((String) obj);
} else if (obj instanceof ComplexKey) {
  builder.setComplexName((ComplexKey) obj);
} else {
  throw new AssertionError("Not a String or ComplexKey");
}
KeyMsg msg = builder.build();

答案 1 :(得分:0)

您可以使用 switch-case:

  public Object demo() {
    KeyMsg keyMsg = KeyMsg.newBuilder().build();
    final KeyMsg.KeyMsgOneOfCase oneOfCase = keyMsg.getKeyMsgOneOfCase();

    switch (oneOfCase) {
      case NAME: return keyMsg.getName();
      case COMPLEX_NAME: return keyMsg.getComplexName();
      case KEY_MSG_ONE_OF_NOT_SET: return null;
    }
  }