私は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
タグを削除することです。これどうやってするの?
[もっと]ポータブルなソリューション:
sed
を使用して生成した後、protoc
を使用してタグを削除します。
* .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の間でそのフラグを移植できないため、ここでは使用されません。
Grpc-gatewayを使用していて、jsonマーシャリング中にデフォルト値が存在する必要がある場合は、servemuxを作成するときに次のオプションを追加することを検討できます。
gwmux := runtime.NewServeMux(runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{OrigName: true, EmitDefaults: true}))
Grpc-gatewayの外で、プロトコルバッファメッセージをマーシャリングする場合は、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
}
omitempty
jsonタグが1778行あたりのprotoc-gen-go source にハードコードされていることがわかりました。
tag := fmt.Sprintf("protobuf:%s json:%q",
g.goTag(message, field, wiretype), jsonName+",omitempty")
ソースを変更して、新しいprotoc-gen-goバイナリを自分で作成するのは簡単です。
特にハッキングされたバイナリalwaysが確実に使用されるようにするため、これはいくつかの理由でお勧めできません。 protobufを再生成する必要がある場合。
Gogo proto( https://github.com/gogo/protobuf )を使用して試すことができます。jsontag拡張機能を使用すると、protoメッセージは次のようになります。
message Status {
int32 code = 1 [(gogoproto.jsontag) = "code"];
string message = 2 [(gogoproto.jsontag) = "message"];
}
必要に応じて、さらにタグを追加することもできます。
Jsonpbパッケージの下のマーシャラーには、EmitDefaultsフィールドがあります。これをtrueに設定すると、構造体のomitemptyタグが無視されます。
https://godoc.org/github.com/golang/protobuf/jsonpb#JSONPBMarshaler
「sed」コマンドを使用して、次のようなファイルからこのテキストを削除できます
sed -i "" -e "s/,omitempty//g" ./api/proto/*.go
args:
-i ""
は同じ名前のファイルを保持することを意味-e "s/,omitempty//g"
= "s/SEARCH/INSERT/g"
のように置き換えるフォーマットencoding/jsonパッケージをmy_jsonなどの独自のフォルダーにコピーし、 omitEmpty フィールドをfalseに変更し、my_json.Marshal()
を使用してstructをjson文字列にエンコードできます。