繁体   English   中英

从字节数组中识别 ProtoBuf 类

[英]Identify ProtoBuf class from byte array

我正在编写一个处理两个 proto 消息的程序,我需要处理从不同来源发送的 byte[],它发送 foo 消息或 bar 消息。 由于我无法弄清楚它属于哪个消息,我使用 Any Class(与 protobuf 一起提供)来解析字节数组并找到它属于哪个类,但遇到了编译时错误。 有没有其他方法可以用来检测我将来是否添加更多 proto 消息类?

//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 类型中的方法 is(Class< T>) 不适用于参数 (Class< Foo>)

Any并不意味着“任何”; 它的意思是“通过 Any 序列化的类型”。 如果你没有用Any存储它:你不能通过Any解码它。

这里的关键点是 protobuf 在消息有效负载中不包含类型元数据。 如果您有 BLOB,您通常无法知道消息类型是什么。 Any通过在包装器 message 中对消息类型进行编码来解决该问题,但您不会在这里使用它。


如果您的设计要让 API 接受两种不同的非Any消息类型,而事先不知道它是哪种类型:您的设计可能很糟糕。 因为这不适用于 protobuf。 在线Fooa=42Foob=42Bar之间实际上没有区别 有效载荷是相同的

a=42 Foo是字节08 2A Barb=42是字节08 2A 08表示“字段 1,编码为 varint”, 2A是原始值为 42 的 varint。

更好的设计可能是特定于您的场景的包装消息:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM