如何在protobuf中实现一个真正的可选字段?

时间:2016-01-20 22:40:23

标签: protocol-buffers

我有一个描述可能每月,每年或特定日期发生的事件的原型。其基本结构是:

enum PeriodType {
  MONTHLY = 1;
  YEARLY = 2;
  SPECIFIC_DATE = 3;
}

message Event {
  PeriodType period_type = 1;
  ...
}

但应该有一种方法来指定发生的日期。所以我做了以下原型:

message Event {
  PeriodType period_type = 1;
  Date period_specific_date = 2;
  ...
}

在我们的内部代码审核期间,该解决方案被禁止。原因是“proto不应包含仅在另一个字段中存在特定值时使用的字段”。我需要以某种方式重写它,以便event period_type == MONTHLYevent.getPeriodSpecificDate()不能调用message Event { message Period { PeriodType period_type = 1; } message PeriodWithDate { Period period = 1; Date period_specific_date = 2; } oneof period { Period period_without_date = 1; PeriodWithDate period_with_date = 2; } ... } 。我怎么能这样做?

一个可能的解决方案是这样做:

p

但这并没有真正解决问题,看起来像一个可怕的矫枉过正。还有其他办法吗?

2 个答案:

答案 0 :(得分:2)

如果给出了日期,则实际上并不需要PeriodType。 所以你可以这样做:

enum RegularPeriod
{
    MONTHLY = 1;
    YEARLY = 2;
}
oneof period
{
    RegularPeriod regular = 1;
    Date specific_date = 2;
}

答案 1 :(得分:1)

  

在我们的内部代码审核期间,该解决方案被禁止。原因是“proto不应包含仅在另一个字段中存在特定值时才使用的字段”。

告诉您的评论者我是Protocol Buffers v2的作者,我认为这条规则是不切实际的。虽然在类型系统中强制执行所有内容很有诱惑力,但实际上Protobuf类型系统的表现力远不足以制定这种硬性规则。在实际使用中,实际上很常见的是具有记录约束的字段,例如“如果字段X具有值Y,则该字段应该仅存在”,并且这确实没问题。

据说,在这种特殊情况下,@ jpa的答案是合理的。它有权衡:你现在在你的代码中有多个级别的分支,这可能很难看,如果你的协议变得更复杂,可能会变得更加丑陋。但它确实设法在类型系统中表达所有约束。

(不接受我的回答,接受@ jpa的。)