>我正在编写一个处理两条原型消息的程序,我需要处理从不同来源发送的 byte[],该消息发送 foo 消息或 bar 消息。由于我无法弄清楚它属于哪个消息,所以我使用 Any 类(随 protobuf 一起提供(来解析字节数组和 查找它所属的类,但遇到编译时错误。是否有任何其他方法可用于检测将来是否添加更多原型消息类?
//Foo.proto
syntax = "proto3";
option java_outer_classname = "FooProto";
message Foo {
int32 a = 1;
}
和第二个原型
//Bar.proto
syntax = "proto3";
option java_outer_classname = "BarProto";
message Bar {
int32 b = 1;
}
法典:
Any anyEvent = Any.parseFrom(protoBytes);
if (any.is(Foo.class)
{
Foo foo = any.unpack(Foo.class);
...
} else {
Bar bar = any.unpack(Bar.class);
...
}
尝试调用 any.is(( 时 if 语句出错:
该方法是(类
( 类型为 Any 不适用于参数 (类 (
Any
并不意味着"any";它的意思是"通过Any序列化的类型"。如果您没有将其与Any
一起存储:则无法通过Any
进行解码。
这里的关键点是 protobuf 在消息有效负载中不包含类型元数据。如果您有 BLOB,则通常无法知道消息类型是什么。Any
通过在包装器消息中对消息类型进行编码来解决这个问题,但此处不会有。
如果你的设计是有一个接受两种不同的非Any
消息类型的API,而事先不知道它是什么:你可能有一个糟糕的设计。因为这不适用于protobuf。在电线上,带a=42
的Foo
和带b=42
的Bar
之间实际上没有区别;有效负载是相同的:
Foo
a=42
是字节08 2A
;Bar
b=42
是字节08 2A
。08
表示"字段 1,编码为 varint",2A
是原始值为 42 的变体。
更好的设计可能是特定于你的方案的包装器消息:
message RootMessage {
oneof test_oneof {
Foo foo = 1;
Bar bar = 2;
}
}
这增加了一个包装层,类似于Any
的工作方式,但效率更高 - 它只知道如何区分整数形式的已知类型,而不必处理每个可能的类型(作为根类型名称(。