gpt4 book ai didi

protocol-buffers - Protobuf 3.0 任何类型的打包/解包

转载 作者:行者123 更新时间:2023-12-03 14:07:28 26 4
gpt4 key购买 nike

我想知道如何转换 Protobuf 任意 类型为原始 Protobuf 消息类型,反之亦然。在 Java 中,从 Message 到 Any 很简单:

Any.Builder anyBuilder = Any.newBuilder().mergeFrom(protoMess.build());

但是我该如何解析 任意 回到原始消息(例如“protoMess”的类型)?我可能可以解析流中的所有内容,然后将其读回,但这不是我想要的。我想有一些这样的转变:
ProtoMess.MessData.Builder protoMessBuilder = (ProtoMess.MessData.Builder) transformToMessageBuilder(anyBuilder)

我怎样才能做到这一点?它已经为 Java 实现了吗? Protobuf Language Guide说有打包和解包方法,但Java中没有。
先感谢您 :)

最佳答案

答案可能有点晚了,但也许这仍然对某人有所帮助。

在当前版本的 Protocol Buffers 3 packunpackavailable in Java .

在您的示例中,包装可以像这样完成:

Any anyMessage = Any.pack(protoMess.build()));

并像这样拆包:

ProtoMess protoMess = anyMessage.unpack(ProtoMess.class);

这里也是处理带有嵌套 Any 的 Protocol Buffers 消息的完整示例留言:

Protocol Buffer 文件

一个带有嵌套 Any 的简单 Protocol Buffer 文件消息可能如下所示:

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() {
// Create child message
ChildMessage.Builder childMessageBuilder = ChildMessage.newBuilder();
childMessageBuilder.setText("Child Text");
// Create parent message
ParentMessage.Builder parentMessageBuilder = ParentMessage.newBuilder();
parentMessageBuilder.setText("Parent Text");
parentMessageBuilder.setChildMessage(Any.pack(childMessageBuilder.build()));
// Return message
return parentMessageBuilder.build();
}

开箱

要从父消息中读取子消息,可以使用以下函数:

public ChildMessage readChildMessage(ParentMessage parentMessage) {
try {
return parentMessage.getChildMessage().unpack(ChildMessage.class);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
return null;
}
}

编辑:

如果您的打包消息可以有不同的类型,您可以读出 typeUrl并使用反射来解包消息。假设您有子消息 ChildMessage1ChildMessage2您可以执行以下操作:

@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;
}
}

关于protocol-buffers - Protobuf 3.0 任何类型的打包/解包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32613667/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com