簡體   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