golang protobuf从生成的json标记中删除空标记
我正在使用带有json代理的google grpc。出于某种原因,我需要从*.pb.go文件中生成的结构中删除golang protobuf从生成的json标记中删除空标记,go,grpc,protocol-buffers,proto3,Go,Grpc,Protocol Buffers,Proto3,我正在使用带有json代理的google grpc。出于某种原因,我需要从*.pb.go文件中生成的结构中删除ommitempty标记 如果我有这样的原始信息 message Status { int32 code = 1; string message = 2; } type Status struct { Code int32 `protobuf:"varint,1,opt,name=code" json:"code,omitempty"` Message string `
ommitempty
标记
如果我有这样的原始信息
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"`
}
生成的结构如下所示
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"`
}
但是我需要从生成的结构中删除
ommitempty
标记。我怎样才能做到这一点呢?我发现省略empty
json标记已硬编码到protoc gen的第1778行:
tag := fmt.Sprintf("protobuf:%s json:%q",
g.goTag(message, field, wiretype), jsonName+",omitempty")
这将很容易改变源代码,并使一个新的protoc gen变为二进制
值得注意的是,这可能是不可取的,不建议这样做有几个原因,特别是因为如果需要重新生成protobufs,您将负责确保始终使用被黑客攻击的二进制文件。一个[更]可移植的解决方案: 通过
protoc
生成标签后,使用sed
剥离标签
生成*.pb.go文件后,我在go:generate脚本中实际使用的示例:
ls *.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}'
注意:
sed-i
(内联替换)在这里不使用,因为该标志在标准OS-X和Linux之间不可移植。您可以将编码/json包复制到自己的文件夹中,例如my_json,并将字段修改为false,然后使用my_json.Marshal()< /COD>将Stutt编码为JSON String。< P>如果您使用GRPC网关,并且需要在JSON封送过程中存在默认值,则可以在创建ServMUX 时考虑添加以下选项
gwmux := runtime.NewServeMux(runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true}))
在grpc网关之外,如果要封送协议缓冲区消息,请使用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
}
您可以尝试使用gogo proto()
使用jsontag扩展,您的proto消息如下所示
message Status {
int32 code = 1 [(gogoproto.jsontag) = "code"];
string message = 2 [(gogoproto.jsontag) = "message"];
}
如果愿意,还可以添加更多标记。jsonpb包下的封送拆收器有一个EmitDefaults字段。将此设置为true,将忽略struct中的ommitempty标记
您可以使用“sed”命令从以下文件中删除此文本
sed -i "" -e "s/,omitempty//g" ./api/proto/*.go
其中args:
-i”“
的意思是保持文件名相同
-e“s/,省略空的//g”
=要替换的格式,如“s/SEARCH/INSERT/g”
你需要原型buf工作正常吗?proto-buf需要这些标签。问题是@jiangid,我正在用我的一个int-feld发送一个0值。但当我发送0值时,grpc网关会忽略该值。我知道还有其他方法,但我想知道如何删除省略空标记。@Sadlil我不确定我是否理解您的问题。如果您发送一个0
值,它将被忽略,因此该字段将保持不变-如果您使用的是零值结构(无论如何,您应该这样做)。我的问题是当我将该结构解析为json时,代码的值为0。json中会忽略该值。但是我需要这个值存在。@Sadlil如果你明确声明:struct.Field=proto.Uint64(0)
它不应该是空的。3年多前的这个答案已经建议使用sed
作为后处理:你没有为源代码添加永久链接,现在很好!此外,gogo
支持自定义标记,例如[(gogoproto.moretags)=“数据存储:\”-\”]
。要切换到gogo
,只需将protoc--go\u out=
更改为protoc--gogofast\u out=
(注意:gogofast也比googleproto快5..10倍!)