在 protobuf 中需要一个 `oneof`?
Require a `oneof` in protobuf?
我想制作一个可以包含多种不同事件类型的 protobuf Event
消息。这是一个例子:
message Event {
required int32 event_id = 1;
oneof EventType {
FooEvent foo_event = 2;
BarEvent bar_event = 3;
BazEvent baz_event = 4;
}
}
这很好用,但让我烦恼的一件事是 EventType
是可选的:我可以只用 event_id
编码一个对象,而 protobuf 不会抱怨。
>>> e = test_pb2.Event()
>>> e.IsInitialized()
False
>>> e.event_id = 1234
>>> e.IsInitialized()
True
有什么方法可以要求设置 EventType
吗?如果重要的话,我正在使用 Python。
根据 Protocol Buffers 文档,不推荐 required
字段规则,并且已在 proto3 中删除。
Required Is Forever You should be very careful about marking fields as required. If at some point you wish to stop writing or sending a required field, it will be problematic to change the field to an optional field – old readers will consider messages without this field to be incomplete and may reject or drop them unintentionally. You should consider writing application-specific custom validation routines for your buffers instead. Some engineers at Google have come to the conclusion that using required does more harm than good; they prefer to use only optional and repeated. However, this view is not universal.
正如上面的文档所说,您应该考虑使用特定于应用程序的验证,而不是将字段标记为 required
。
无法将 oneof
标记为 "required"(即使在 proto2 中),因为在引入 oneof
时,人们已经广泛接受字段可能永远不应该是 "required",所以设计者没有费心去实施一种方法来使 oneof
成为必需的。
使用 options
syntax,有多种方法可以指定验证规则和 auto-generate 验证例程的代码。
您可以这样使用 https://github.com/envoyproxy/protoc-gen-validate:
import "validate/validate.proto";
message Event {
required int32 event_id = 1;
oneof EventType {
option (validate.required) = true;
FooEvent foo_event = 2;
BarEvent bar_event = 3;
BazEvent baz_event = 4;
}
}
“您应该考虑为您的缓冲区编写 application-specific 自定义验证例程。”我们在这里 auto-generating 这样的自定义验证例程。
但是等等,这是否违背了 protobuf 规范的精神?为什么 required
不好而 validate
好?我自己的回答是,protobuf 规范非常关心“代理”,即 serializes/deserializes 消息的软件,但它自己几乎没有业务逻辑。这样的软件可以简单地省略验证(这是一个选项),但它不能省略 required
(它必须使消息无法解析)。
对于业务逻辑方面,根据我的经验,所有这些都不是大问题。
我想制作一个可以包含多种不同事件类型的 protobuf Event
消息。这是一个例子:
message Event {
required int32 event_id = 1;
oneof EventType {
FooEvent foo_event = 2;
BarEvent bar_event = 3;
BazEvent baz_event = 4;
}
}
这很好用,但让我烦恼的一件事是 EventType
是可选的:我可以只用 event_id
编码一个对象,而 protobuf 不会抱怨。
>>> e = test_pb2.Event()
>>> e.IsInitialized()
False
>>> e.event_id = 1234
>>> e.IsInitialized()
True
有什么方法可以要求设置 EventType
吗?如果重要的话,我正在使用 Python。
根据 Protocol Buffers 文档,不推荐 required
字段规则,并且已在 proto3 中删除。
Required Is Forever You should be very careful about marking fields as required. If at some point you wish to stop writing or sending a required field, it will be problematic to change the field to an optional field – old readers will consider messages without this field to be incomplete and may reject or drop them unintentionally. You should consider writing application-specific custom validation routines for your buffers instead. Some engineers at Google have come to the conclusion that using required does more harm than good; they prefer to use only optional and repeated. However, this view is not universal.
正如上面的文档所说,您应该考虑使用特定于应用程序的验证,而不是将字段标记为 required
。
无法将 oneof
标记为 "required"(即使在 proto2 中),因为在引入 oneof
时,人们已经广泛接受字段可能永远不应该是 "required",所以设计者没有费心去实施一种方法来使 oneof
成为必需的。
使用 options
syntax,有多种方法可以指定验证规则和 auto-generate 验证例程的代码。
您可以这样使用 https://github.com/envoyproxy/protoc-gen-validate:
import "validate/validate.proto";
message Event {
required int32 event_id = 1;
oneof EventType {
option (validate.required) = true;
FooEvent foo_event = 2;
BarEvent bar_event = 3;
BazEvent baz_event = 4;
}
}
“您应该考虑为您的缓冲区编写 application-specific 自定义验证例程。”我们在这里 auto-generating 这样的自定义验证例程。
但是等等,这是否违背了 protobuf 规范的精神?为什么 required
不好而 validate
好?我自己的回答是,protobuf 规范非常关心“代理”,即 serializes/deserializes 消息的软件,但它自己几乎没有业务逻辑。这样的软件可以简单地省略验证(这是一个选项),但它不能省略 required
(它必须使消息无法解析)。
对于业务逻辑方面,根据我的经验,所有这些都不是大问题。