Java协议缓冲区 - 使用扩展字段构建子消息

3

如何在协议缓冲区中添加扩展字段来构建子消息。在C ++中,一种方法是使用反射接口的MutableMessage(Message, FieldDescriptor)。在Java中,我们如何执行类似的操作?

我是新手,对协议缓冲区不是很了解。

2个回答

4

跟随Jonathon的答案,这里是Java中创建和访问扩展的示例。

Protobuf定义:

message Message
{
    extensions 100 to max;

    required uint64 A = 1;
}

message Event
{
    extend Message { 
        required Event ext = 101; 
        optional string name = 102;
    }

    extensions 100 to max;

    required uint64 B = 1;

}

使用扩展功能:

Extension01.Message.Builder bm = Extension01.Message.newBuilder();
Extension01.Message.Builder bm1 = Extension01.Message.newBuilder();
Extension01.Event.Builder be = Extension01.Event.newBuilder();
FileOutputStream out = new FileOutputStream(extFileOut);

be.setB(5678);


bm.setA(123);
bm.setExtension(Extension01.Event.ext, be.build()); // set the extension value

bm.build().writeDelimitedTo(out);
out.close();

FileInputStream in = new FileInputStream(extFileOut);

ExtensionRegistry registry = ExtensionRegistry.newInstance(); // create extension registry
Extension01.registerAllExtensions(registry);  // Allocate the extensions 
bm1.mergeDelimitedFrom(in, registry);
in.close();

Event extension = bm1.getExtension(Extension01.Event.ext); // get the extension
if (extension == null) {
    System.out.println("No extension");
} else {
    System.out.println(extension.getB());
}

编辑:

Line setting extension value:

bm.setExtension(Extension01.Event.ext, be.build());

变量Extension01.Event.ext是由协议缓冲区生成的,可以用于获取/放置扩展值。

编辑2:

这就是我认为extensionInfo被使用的方式(我自己还没有尝试):

ExtensionInfo extensionInfo = registry.findExtensionByNumber(..., 101);
bm1.getField(extensionInfo.descriptor);
bm1.setField(extensionInfo.descriptor, value)

我无法完全理解它。参考您给出的解决方案+protobuf javadocs,我能够通过使用给定的扩展号码(我使用registerAllExtensions()和findExtensionByNumber())获取extensioninfo。然而,现在我需要使用setExtension()生成一个带有嵌入式扩展的消息,其中GeneratedExtension是其中一个参数。您知道如何使用extensioninfo设置扩展吗?还是我的做法有问题? - pree
请参见上面示例中的bm.setExtension行。 - Bruce Martin
1
由协议缓冲区生成的变量Extension01.Event.ext可用于设置和检索扩展的值。 - Bruce Martin
1
对于生成的消息,它并不是真正按照那种方式工作。在注册表类上有一个getExtensionByName方法,然后在getField??方法中使用描述符变量;需要进行一些调整。或者可以通过DynamicMessage按编号检索,但是使用DynamicMessages时没有Generated-Protocol缓冲区。 - Bruce Martin
是的,你说得对。我确实尝试了我在第一条评论中提到的东西,但是在调用findExtenionByNumber()时它返回了ExtensionInfo实例。因此一直在努力找出如何将其转换为标识符,以便可以将其传递给setExtension()方法 :) - pree
显示剩余3条评论

3
使用setExtension方法。假设:
message Bar {
  extend Foo {
    optional string foo_string = 1;
  }
}

您可以这样构建Bar消息:
Foo foo = Foo.newBuilder()
    .setExtension(Bar.fooString, "My foo string")
    .build();

请参考Protocol Buffers的Java生成代码文档有关扩展的更多详细信息。


谢谢。我该如何从给定的扩展号码中检索扩展标识符? - pree
Protocol Buffers 生成一个静态的 final 变量,可以用来访问扩展类。 - Bruce Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接