【问题标题】:How to model JSON array as protobuf definition如何将 JSON 数组建模为 protobuf 定义
【发布时间】:2018-04-07 07:38:58
【问题描述】:

我正在使用 protobuf 在 golang 中编写一个新服务。我想在 .proto 文件中对以下请求 JSON 建模。

[
   {
    "var": ["myVariable1","myVariable2"], 
    "key1": 123123,
    "key2": 1122,
    "key3": "abcd-0101"
   },
  { 
    "var": ["myVariable1"], 
    "key1": 123124,
    "key2": 1123,
    "key3": "abcd-0102"
  },
] 

目前有两个问题:

  • 事先不知道每个数组元素中的键,因此我无法在 .proto 文件中创建消息并使其重复。我需要保留它的地图
  • 我无法对只是一个没有键的数组的 json 建模。每次我这样做时,都会显示以下错误:无法解码请求:json:无法将数组解组为 Go 值

以下是我的 .proto 文件:

syntax = "proto3";

package pb;

import "google/protobuf/empty.proto";
import "google/api/annotations.proto";

service Transmitter {
  rpc GetVariables(GetVariablesRequest) returns (GetVariablesResponse) {
    option (google.api.http) = {
                post: "/api/v1/{Service}/getVars"
                body: "*"
            };
  };
}


message GetVariablesRequest {
  string Service = 1;
  repeated GetVarInput in = 2;
}

message GetVariablesResponse {
  string msg = 1;
}

message GetVarInput {
  map<string,string> Input = 2;
}

我尝试使用字节而不是重复的 GetVarInput,但它总是为空。还尝试了 body: "*" 和 body : "in"

请提供一些指示。

【问题讨论】:

  • 你不能在你的 json blob 中给数组一些占位符名称吗?例如{ "data" : [ {...}, {...} ] }

标签: arrays json go protocol-buffers grpc


【解决方案1】:
service UserService {
  rpc GetUsers(GetUsersRequest) returns (Users) {
    option (google.api.http) = {
      get : "/users"
    };
  };

  rpc GetUser(GetUserRequest) returns (User) {
    option (google.api.http) = {
      get : "/users/{user_id}"
    };
  };
}

message User {
  string id = 1;
  string display_name = 2;
  string icon_image_path = 3;
  string background_image_path = 4;
  string profile = 5;
  string email = 6;
  google.protobuf.Timestamp created_at = 8;
  google.protobuf.Timestamp updated_at = 9;
  google.protobuf.Timestamp deleted_at = 10;
}

message Users {
  repeated User user = 1;
}

message GetUsersRequest {}
message GetUserRequest { string user_id = 1; }

【讨论】:

  • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的回答添加解释并说明适用的限制和假设。
【解决方案2】:

另一种方法是在 .proto 文件中使用 Any 消息。在这种情况下,您可以使用所需的任何 GO 类型重复映射。但是这种方法有点开销,因为它为您提供了使用强类型编程语言的灵活性。这是一个例子:

message Any {
    string type = 1;
    bytes value = 2;
}

在你的 GO 代码中:

func GetRPCAnyValue(value interface{}) *pb.Any {
    bValue, type_val, _ := MarshlizeValue(value)
    return &pb.Any{
        Type: type_val,
        Value: bValue,
    }
}

【讨论】:

    【解决方案3】:

    Satyam Zode 的回答似乎是最合理的。

    在您最初的问题中,您试图保持 JSON 的所有灵活性和动态特性,在这种情况下,尝试将其转换为 protobuf 毫无意义。您可以只拥有一个包含 json 的字符串字段。

    但是,protobuf 确实可以很好地处理未来对 RequestMessage 内容的更改,因此您不必知道最终的字段集。只需关注Updating a Message Type 即可让它们在不同的 .proto 文件版本之间保持兼容。

    【讨论】:

      【解决方案4】:

      你可以像这样为你的 json 写一条消息:

      message RequestMessage {
         string var = 0;
         double key1 = 1;
         double key2 = 2;
         string key3 = 3;
      }
      

      此外,您可以创建另一个包含RequestMessage 数组的消息

      message Request {
         repeated RequestMessage request = 0;
      }
      

      【讨论】:

      • 只有上面的变化是 - proto3中不允许零或负数。所以以 1 开始列。这对我有用,谢谢
      • 我认为请求将映射到 json 对象而不是数组。这将是{“请求”:[]}。如何直接映射到数组?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多