TypeScript / JavaScript gRPC google.protobuf.Struct 无法读取

问题描述 投票:0回答:4

我有一个 TypeScript 服务器尝试使用 Struct 读取 JSON 对象,但它似乎仅部分适用于包含“fields”键的对象,然后该对象需要一个对象作为值。尽管如此,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.js typescript protocol-buffers grpc grpc-node
4个回答
5
投票

真正让我困惑的是我试图传递普通的 JSON 对象并期望读取它们。重点是,从客户端来看,JSON 对象需要以非常特定的方式进行编码。

例如:

"payload": {
    "fields": {
      "name": {
        "stringValue": "joe"
      },
      "age": {
        "numberValue": 28
      }
    }
  }

您可以通过查看此处的 Struct proto 文件来确定消息的格式:https://googleapis.dev/nodejs/asset/latest/v1_doc_google_protobuf_doc_struct.js.html


3
投票

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

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

Struct
的 JSON 表示是 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 的作者。创建结构非常简单:

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

2
投票

首先,安装

@types/google-protobuf
和:

  let rqm = new UpdateTicketRequest();
  rqm.setTicketId("1");
  rqm.setPayload(Struct.fromJavaScript({
    Hello:{
      whatever: 0,
    }
  });
  //and call the api....
  UpdateTicket(rqm);

0
投票

另一种方法是使用 pb-util

const {struct} = require('pb-util');

const structValue = struct.encode({foo: 'bar'});
// => {
//   fields: {
//     foo: {
//       kind: 'stringValue',
//       stringValue: 'bar'
//     }
//   }
// }

© www.soinside.com 2019 - 2024. All rights reserved.