Google Protobuf - 缺少类型注册表描述符

Rok*_*545 3 json protocol-buffers

我有一些带有“@type”字段的 Google Protobuf json,其值是一个 URI,它将告诉某人 Protobuf 消息的类型,例如 "@type": "type.googleapis.com/llcore.ModemDataAtlas"。根据我的理解,这些 json 字符串应该首先序列化为“Any”类型。每当我这样做时,我都会收到以下错误:

System.InvalidOperationException: Type registry has no descriptor for type name ''llcore.ModemMessage'
Run Code Online (Sandbox Code Playgroud)

这是我的代码:

string jsonString = "";
string jsonPath = @"C:\Users\user\Documents\TestRepos\ExampleProto\protoType.json";
using (StreamReader reader = new StreamReader(jsonPath))
{
    jsonString = reader.ReadToEnd();
}

Any anyProto = Any.Parser.ParseJson(msg); // Exception occurs here
Run Code Online (Sandbox Code Playgroud)

有谁知道如何正确反序列化为 Protobuf Any 类?如何创建类型注册表并为其添加描述符?

Mai*_*aik 5

首先让我解释一下为什么你不能简单地解析/序列化任意 JSON Any(或反之亦然)。Any本身有2个字段:

  • typeUrl- 就你的情况而言"type.googleapis.com/llcore.ModemDataAtlas"
  • value- 编码为二进制 protobuf 的实际内容

二进制 protobuf 将每个字段编码为一对键和内容,可以将其视为 Map。关键不是字段的名称,而是原型定义中为字段指定的编号。

JSON 对象也是一个 Map,但它使用字段名称作为索引。因此,如果没有该类型的任何类型信息(描述符),JSON 解析器将不知道如何将 JSON 对象的命名字段映射到仅由数字标识的二进制编码版本。

只是为了明确一点:您无法解析/序列化编码为Any!的未知类型。您的应用程序需要了解它们,要么通过将描述符静态编译到其中,要么通过在运行时查找类型描述符。TypeRegistry这基本上是允许您在运行时加载描述符的要点,但是您必须自己提供这种查找类型的基础结构。

为了在您的情况下实现此功能,您的应用程序需要了解Any. 然后您可以创建一个TypeRegistry并将其传递给JsonParser构造函数。我不是C#开发人员,但大致如下:

var registry = TypeRegistry.FromMessages(MyMessage.Descriptor);
var parser = new JsonParser(new JsonParser.Settings(20, registry));
var message =  parser.Parse<Any>(payload);
Run Code Online (Sandbox Code Playgroud)