如何在protobuf 3中定义可选字段

问题描述 投票:43回答:5

我需要在protobuf(proto3语法)中指定带有可选字段的消息。就proto 2语法而言,我想表达的信息是这样的:

message Foo {
    required int32 bar = 1;
    optional int32 baz = 2;
}

根据我的理解,“可选”概念已从语法proto 3(以及所需概念)中删除。虽然不清楚替代方法 - 使用默认值来声明尚未从发送方指定字段,但如果默认值属于有效值域,则会留下歧义(例如考虑布尔类型)。

那么,我应该如何对上面的消息进行编码?谢谢。

protocol-buffers protocol-buffers-3
5个回答
73
投票

在proto3中,所有字段都是“可选的”(因为如果发送方未能设置它们,则不是错误)。但是,字段不再是“可空的”,因为没有办法区分显式设置为默认值的字段与根本未设置的字段之间的区别。

如果您需要一个“null”状态(并且没有可用于此的超出范围的值),那么您将需要将其编码为单独的字段。例如,你可以这样做:

message Foo {
  bool has_baz = 1;  // always set this to "true" when using baz
  int32 baz = 2;
}

或者,您可以使用oneof

message Foo {
  oneof baz {
    bool baz_null = 1;  // always set this to "true" when null
    int32 baz_value = 2;
  }
}

oneof版本在线上更明确,更有效,但需要了解oneof值如何工作。

最后,另一个完全合理的选择是坚持使用proto2。 Proto2并没有被弃用,事实上很多项目(包括Google内部)都非常依赖proto2中删除的proto2功能,因此它们可能永远不会切换。因此,在可预见的将来继续使用它是安全的。


48
投票

一种方法是使用oneof,如接受的答案中建议的那样。

另一个是使用包装器对象。你不需要像google已经提供的那样自己编写它们:

在.proto文件的顶部添加此导​​入:

import "google/protobuf/wrappers.proto";

现在,您可以为每种简单类型使用特殊包装:

DoubleValue
FloatValue
Int64Value
UInt64Value
Int32Value
UInt32Value
BoolValue
StringValue
BytesValue

所以要回答原始问题,这种包装的用法可能是这样的:

message Foo {
    int32 bar = 1;
    google.protobuf.Int32Value baz = 2;
}

现在,例如在Java中我可以做类似的事情:

if(foo.hasBaz()) { ... }


16
投票

根据Kenton的回答,一个更简单但更有效的解决方案如下:

message Foo {
    oneof optional_baz { // "optional_" prefix here just serves as an indicator, not keyword in proto2
        int32 baz = 1;
    }
}

4
投票

扩展@cybersnoopy的建议here

如果您的.proto文件包含如下消息:

message Request {
    oneof option {
        int64 option_value = 1;
    }
}

您可以使用案例选项provided (java generated code)

所以我们现在可以编写如下代码:

Request.OptionCase optionCase = request.getOptionCase();
OptionCase optionNotSet = OPTION_NOT_SET;

if (optionNotSet.equals(optionCase)){
    // value not set
} else {
    // value set
}

0
投票

您可以通过将引用与默认实例进行比较来找到是否已初始化:

GRPCContainer container = myGrpcResponseBean.getContainer();
if (container.getDefaultInstanceForType() != container) {
...
}
© www.soinside.com 2019 - 2024. All rights reserved.