我想知道如何将Protobuf Any Type转换为原始的Protobuf消息类型,反之亦然.在 Java中从Message to Any很容易: Any.Builder anyBuilder = Any.newBuilder().mergeFrom(protoMess.build()); 但是我如何解析任何回到原始
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 pack和unpack是available in 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() { // 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并使用反射来解压缩消息.假设您有子消息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; } }