繁体   English   中英

如何使用 Java 中的描述符将协议缓冲区二进制转换为 JSON

[英]How to convert protocol buffers binary to JSON using the descriptor in Java

我有一个带有“任何”众所周知类型的字段的消息,它可以保存任何类型的序列化 protobuf 消息。

我想将此字段转换为其 json 表示形式。

我知道字段名称是必需的,通常您需要在应用程序中加载生成的类才能工作,但我正在寻找一种方法来使用描述符来做到这一点。

首先,我解析描述符:

 FileInputStream descriptorFile = new FileInputStream("/descriptor");
DescriptorProtos.FileDescriptorSet fdp = DescriptorProtos.FileDescriptorSet.parseFrom(descriptorFile);

然后,遍历包含的消息并找到正确的消息(使用“Any”类型的 URL,其中包含包和消息名称。我将其添加到用于格式化 JSON 的 TypeRegistry。

JsonFormat.TypeRegistry.Builder typeRegistryBuilder = JsonFormat.TypeRegistry.newBuilder();

String messageNameFromUrl = member.getAny().getTypeUrl().split("/")[1];

for (DescriptorProtos.FileDescriptorProto file : fdp.getFileList()) {
    for (DescriptorProtos.DescriptorProto dp : file.getMessageTypeList()) {
        if (messageNameFromUrl.equals(String.format("%s.%s", file.getPackage(), dp.getName()))) {

            typeRegistryBuilder.add(dp.getDescriptorForType()); //Doesn't work.
            typeRegistryBuilder.add(MyConcreteGeneratedClass.getDescriptor()); //Works

            System.out.println(JsonFormat.printer().usingTypeRegistry(typeRegistryBuilder.build()).preservingProtoFieldNames().print(member.getAny()));
            return;
        }

    }
}

问题似乎是解析描述符使我可以访问Descriptors.DescriptorProto对象,但我认为无法获取类型注册表所需的Descriptors.Descriptor对象。 我可以使用 getDescriptor() 访问具体类的描述符并且有效,但是我试图通过从应用程序外部访问预先生成的描述符文件来在运行时格式化 JSON,因此我没有可调用的具体类getDescriptor()

如果我可以使用“Any”字段的类型 URL 来解析Type对象并使用它来生成 JSON,那就更好了,因为它似乎也具有此过程所需的字段编号和名称。

任何帮助表示赞赏,谢谢!

如果将DescriptorProtos.FileDescriptorProto转换为Descriptors.FileDescriptor ,则后者具有返回List<Descriptor>getMessageTypes()方法。

以下是取自我正在开发的名为okgrpc的开源库的 Kotlin 代码片段。 这是在 Java 中创建动态 gRPC 客户端/CLI 的首次尝试。

private fun DescriptorProtos.FileDescriptorProto.resolve(
        index: Map<String, DescriptorProtos.FileDescriptorProto>,
        cache: MutableMap<String, Descriptors.FileDescriptor>
): Descriptors.FileDescriptor {
    if (cache.containsKey(this.name)) return cache[this.name]!!

    return this.dependencyList
        .map { (index[it] ?: error("Unknown dependency: $it")).resolve(index, cache) }
        .let {
            val fd = Descriptors.FileDescriptor.buildFrom(this, *it.toTypedArray())
            cache[fd.name] = fd
            fd
        }
}

暂无
暂无

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

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