热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何在protobuf3中定义可选字段

如何解决《如何在protobuf3中定义可选字段》经验,为你挑选了3个好方法。

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

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

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

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



1> Kenton Varda..:

在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功能,因此它们可能永远不会切换.因此,在可预见的将来继续使用它是安全的.


我找到了消息Foo {oneof baz {int32 baz_value = 1; 很好地工作.
@MaxP您的解决方案有效,但我建议在空消息上使用布尔值.要么将在线路上占用两个字节,但空消息将占用相当多的CPU,RAM和生成的代码膨胀来处理.

2> VM4..:

一种方法是使用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()) { ... }


这是如何运作的?当`baz = null`且未通过`baz`时,两种情况下都有'hasBaz()`说成'false'!

3> CyberSnoopy..:

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

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


基本上,其中一个名字很差.它意味着"至多一个".总有一个可能的空值.
推荐阅读
author-avatar
张兵在江湖
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有