从字节数组中识别 ProtoBuf 类



>我正在编写一个处理两条原型消息的程序,我需要处理从不同来源发送的 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=42Foo和带b=42Bar之间实际上没有区别;有效负载是相同的

Fooa=42是字节08 2A;Barb=42是字节08 2A08表示"字段 1,编码为 varint",2A是原始值为 42 的变体。

更好的设计可能是特定于你的方案的包装器消息:

message RootMessage {
oneof test_oneof {
Foo foo = 1;
Bar bar = 2;
}
}

这增加了一个包装层,类似于Any的工作方式,但效率更高 - 它只知道如何区分整数形式的已知类型,而不必处理每个可能的类型(作为根类型名称(。

最新更新