我有一些带有“@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'
这是我的代码:
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
有谁知道如何正确反序列化为 Protobuf Any 类?我如何着手创建类型注册表并为其添加描述符?
最佳答案
首先让我解释一下为什么您不能简单地将任意 JSON 解析/序列化为 Any
(反之亦然)。 Any
本身有 2 个字段:
typeUrl
- 在您的情况下"type.googleapis.com/llcore.ModemDataAtlas"
value
- 编码为二进制 protobuf 的实际内容
二进制 protobuf 将每个字段编码为一对键和内容,可以将其视为 Map。关键不是字段的名称,而是原型(prototype)定义中赋予字段的编号。
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);
关于json - Google Protobuf - 缺少类型注册表的描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57634281/