golang protobuf从生成的json标签中删除omitempty标签

时间:2016-01-11 07:32:09

标签: go grpc protocol-buffers proto3

我正在使用带有json代理的google grpc。出于某种原因,我需要从* .pb.go文件中生成的结构中删除omitempty标记。

如果我有这样的原型消息

message Status {
  int32 code = 1;
  string message = 2;
}

生成的结构看起来像这样

type Status struct {
  Code int32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"`
  Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
}

但我需要从生成的结构中删除omitempty标记。我怎么能这样做?

7 个答案:

答案 0 :(得分:3)

[更多]便携式解决方案:

通过sed生成后,使用protoc去除标记。

我实际使用的示例:生成* .pb.go文件后生成脚本:

ls *.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}'

注意:此处未使用sed -i(内联替换),因为该标志在标准OS-X和Linux之间不可移植。

答案 1 :(得分:2)

如果您使用的是grpc-gateway并且需要在json编组期间出现默认值,则可以考虑在创建servemux时添加以下选项

    gwmux := runtime.NewServeMux(runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true}))

在grpc-gateway之外,如果要编组protocul缓冲区消息,请使用github.com/golang/protobuf/jsonpb包而不是encoding/json

func sendProtoMessage(resp proto.Message, w http.ResponseWriter) {
    w.Header().Set("Content-Type", "application/json; charset=utf-8")
    m := jsonpb.Marshaler{EmitDefaults: true}
    m.Marshal(w, resp) // You should check for errors here
}

答案 2 :(得分:1)

我发现{17}行omitempty json标记被硬编码到protoc-gen-go source中:

tag := fmt.Sprintf("protobuf:%s json:%q",
    g.goTag(message, field, wiretype), jsonName+",omitempty")

很容易改变来源并自己创建一个新的protoc-gen-go二进制文件。

值得注意的是,这可能是不可取的,并且由于多种原因不推荐,特别是因为如果需要重新生成protobufs,您将负责确保被黑客二进制总是被使用。

答案 3 :(得分:1)

您可以尝试使用gogo proto(https://github.com/gogo/protobuf) 使用jsontag扩展名,您的原始消息看起来像

message Status {
  int32 code = 1 [(gogoproto.jsontag) = "code"];
  string message = 2 [(gogoproto.jsontag) = "message"];
}

如果愿意,还可以添加更多标签。

答案 4 :(得分:0)

您可以将encoding / json包复制到您自己的文件夹(例如my_json),并将omitEmpty字段修改为false,并使用my_json.Marshal()将结构编码为json字符串。

答案 5 :(得分:0)

jsonpb软件包下的Marshaler有一个EmitDefaults字段。将其设置为true,将只忽略struct中的omitempty标签。

https://godoc.org/github.com/golang/protobuf/jsonpb#JSONPBMarshaler

答案 6 :(得分:0)

您可以使用“ sed”命令从以下文件中删除此文本

-i ""

其中args:

  1. -e "s/,omitempty//g"的意思是文件名相同
  2. "s/SEARCH/INSERT/g" =类似于$QQ = "UPDATE T_IMB19 SET SUM1=$SUMA, SUM2=$SUMB, TOTAL=$SUMTOT WHERE Navn='$rows[Navn]'"; mysqli_query($con,$QQ); 的格式