首页 > 解决方案 > TypeScript / JavaScript gRPC google.protobuf.Struct 无法读取

问题描述

我有一个 TypeScript 服务器尝试使用 Struct 读取 JSON 对象,但它似乎仅对包含“字段”键的对象部分工作,然后期望对象作为值。尽管如此,Struct 应该适用于任何 JSON 对象。

使用 BloomRPC 我正在尝试以下消息:

{
  "payload": {
    "fields": {
      "Hello": {
        "whatever": 0
      }
    }
  }
}

服务器读取:

{ fields: { Hello: {} } }

如果我发送:

{
  "payload": {
    "anotherfield": {
      "HelloWorld": {
        "whatever": 0
      }
    }
  }
} 

我在服务器上得到一个空对象。

简化的 protobuf 文件如下所示:

syntax = "proto3";

import "google/protobuf/struct.proto";

// The service definition.
service TestTicketService {
  rpc UpdateTicket (UpdateTicketRequest) returns (UpdateTicketResponse);
}

// The request message containing the required ticket information.
message UpdateTicketRequest {
    string ticketId = 1;
    google.protobuf.Struct payload = 2;
}

// The response message containing any potential error message
message UpdateTicketResponse {
  string error = 1;
}

知道为什么 google/protobuf/struct.proto 不能按预期工作吗?

标签: node.jstypescriptprotocol-buffersgrpcgrpc-node

解决方案


结构的想法是你可以存储任意数据——但只能存储简单的类型:null、number、string、bool、array 和 object。

这完美地映射到 JSON,这不是偶然的。google.protobuf.Struct 消息具有特殊的 JSON 表示:

JSON 表示Struct是 JSON 对象。

所以你可以将任何 JSON 字符串解析成一个 protobuf Struct,当再次序列化为 JSON 时,你也会再次得到相同的 JSON 字符串。

需要注意的是,解析后的 Struct 的内存表示不等于 JSON 对象。Protobuf 没有动态字段,必须以更复杂的方式表示 JSON 数据。这就是为什么struct.proto定义了一些其他类型。

当您想在 JavaScript 中创建 Struct 时,创建所需的 JSON 对象可能是最简单的方法:

var jsonObject = {foo: "bar"};
var jsonString = JSON.stringify(jsonObject);

现在您可以从这个 jsonObject 或 jsonString 解析您的 Struct,并将结果 Struct 作为字段值放入另一个 protobuf 消息中。

由于您已经在使用 TypeScript,因此可能值得查看 protobuf 的替代 TypeScript 实现之一。我是protobuf-ts的作者。创建 Struct 非常简单:

let struct = Struct.fromJson({foo: "bar"});

推荐阅读