7

我在使用 Protoc 和包含可空字符串字段的现有结构时遇到了一些问题。

我试图序列化以进行传输的结构包含一堆在 json 中可以为空的字段(因此我们可以区分null,""和一个设定值)。

type Message struct {
  Path *string `json:"path"`
}

因此,如果用户发送一个空的 json 字符串{},则 Path 将是nil而不是"",而{"path":""}它也是有效的,并且与{"path": null}.

我提出的proto3声明显然看起来像这样(并且是可选的,required并且optional从 proto3 中删除:

syntax = "proto3";
message Message {
  string Path = 1;
}

运行 Protoc 后,我最终得到一个看起来像这样的结构,并且所有值都是string并且无法将它们声明为*string

type Message struct {
  Path string `protobuf:"bytes,1,opt,name=Path,proto3" json:"Path,omitempty"`
}

显然我不能从我现有的结构中分配给这个数组。但是,即使我要target.Path = *source.Path使用适当的空指针检查等编写繁琐的映射代码,我也会失去源结构 ( nil, "", "value") 的三重含义。

关于如何在此处进行操作或 Go Protobuf 是否有扩展来执行此操作的任何建议?或者如何描述这个原型声明?

4

3 回答 3

6

即使未设置字段,Proto3 也会返回零值。目前无法区分字段是否已设置。

请参阅 Github 问题#15

可能的解决方案:

  • 使用proto2而不是proto3
  • 使用 gogoproto 的可为扩展。
  • 使用google.protobuf.FieldMask扩展,请参阅 Google API 设计指南中的常见设计模式:部分响应输出字段
于 2019-07-15T22:05:16.530 回答
1

https://stackoverflow.com/a/62566052 proto3 支持可选带标志--experimental_allow_proto3_optional

于 2021-03-25T07:42:38.767 回答
0

就我而言,我用几个包解决了这个问题:

  1. https://github.com/gogo/protobuf
  2. https://github.com/golang/protobuf

我的原型文件如下所示:

syntax = "proto3";

import "google/protobuf/wrappers.proto";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";

message Message {
  google.protobuf.StringValue path = 1 [(gogoproto.wktpointer) = true];
}

我使用的生成 go 代码的命令如下所示:

protoc -I. -I%GOPATH%/src --gogofaster_out=plugins=grpc:. proto/*.proto

生成的 go 文件如下所示:

type Message struct {
    Path *string `protobuf:"bytes,1,opt,name=path,json=path,proto3,wktptr" json:"path,omitempty"`
}
于 2020-05-15T07:46:23.683 回答