答案可能有点晚,但是也许仍然对某些人有帮助。
在当前版本的 Protocol Buffers 3 中,
pack
和
unpack
在 Java 中是
可用的。
在您的示例中,打包可以像这样完成:
Any anyMessage = Any.pack(protoMess.build()));
并且像这样解包:
ProtoMess protoMess = anyMessage.unpack(ProtoMess.class);
以下是一个处理嵌套 Any
消息的 Protocol Buffers 消息的完整示例:
ProtocolBuffers 文件
一个包含嵌套 Any
消息的简单 Protocol Buffers 文件可能如下所示:
syntax = "proto3";
import "google/protobuf/any.proto";
message ParentMessage {
string text = 1;
google.protobuf.Any childMessage = 2;
}
一个可能的嵌套信息如下:
syntax = "proto3";
message ChildMessage {
string text = 1;
}
打包
为了构建完整的消息,可以使用以下函数:
public ParentMessage createMessage() {
ChildMessage.Builder childMessageBuilder = ChildMessage.newBuilder();
childMessageBuilder.setText("Child Text");
ParentMessage.Builder parentMessageBuilder = ParentMessage.newBuilder();
parentMessageBuilder.setText("Parent Text");
parentMessageBuilder.setChildMessage(Any.pack(childMessageBuilder.build()));
return parentMessageBuilder.build();
}
解包
要从父消息中读取子消息,可以使用以下函数:
public ChildMessage readChildMessage(ParentMessage parentMessage) {
try {
return parentMessage.getChildMessage().unpack(ChildMessage.class);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
编辑:
如果你的打包消息可以有不同的类型,你可以读取typeUrl
并使用反射来解包消息。假设你有子消息ChildMessage1
和ChildMessage2
,你可以这样做:
@SuppressWarnings("unchecked")
public Message readChildMessage(ParentMessage parentMessage) {
try {
Any childMessage = parentMessage.getChildMessage();
String clazzName = childMessage.getTypeUrl().split("/")[1];
String clazzPackage = String.format("package.%s", clazzName);
Class<Message> clazz = (Class<Message>) Class.forName(clazzPackage);
return childMessage.unpack(clazz);
} catch (ClassNotFoundException | InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
为了进一步处理,您可以使用instanceof
确定消息的类型,但这并不是非常高效的。如果您想获取特定类型的消息,则应直接比较typeUrl
:
public ChildMessage1 readChildMessage(ParentMessage parentMessage) {
try {
Any childMessage = parentMessage.getChildMessage();
String clazzName = childMessage.getTypeUrl().split("/")[1];
if (clazzName.equals("ChildMessage1")) {
return childMessage.unpack("ChildMessage1.class");
}
return null
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}
readChildMessage
,没有其他方法吗?如果可能会有数十种不同的消息,该怎么办?只需添加新的try-catch
块吗?即便使用switch-case
等也绝对不可接受。 - user4063815typeURL
获取打包消息的名称。这允许通过反射解包任何消息或直接决定如何处理消息。我在我的答案中添加了两个示例,希望这有所帮助。 - sundance