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

标签 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'

这是我的代码:

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/

相关文章:

sql - Entity Framework (LINQ) 可以根据 JSON where 子句选择行吗?

hadoop - Hive Protocol Buffer - 在 Hive 中创建表时出现 NullPointerException

c++ - 我可以使用 C++ 从 Protocol Buffer 序列化/反序列化 JSON 吗?

java - Protobuf 中的默认枚举值是多少?

java - Google Protocol Buffers 在网络软件中的作用

java - 如何强制 JSON-lib 的 JSONObject.put(..) 转义包含 JSON 的字符串?

json - 使用 Angular 服务传递 json 数据

jquery - 使用AJAX检查数据库中是否存在用户名

C# 如何等待返回 Task<dynamic> 的方法?

java - Android 上的协议(protocol)生成的 Grpc 服务中的方法编码器错误