web-dev-qa-db-ja.com

golang protobufは生成されたjsonタグからomitemptyタグを削除します

私は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タグを削除することです。これどうやってするの?

16
sadlil

[もっと]ポータブルなソリューション:

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の間でそのフラグを移植できないため、ここでは使用されません。

5
Jay Taylor

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
}
3
DeeSilence

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を再生成する必要がある場合。

3
Jiang YD

Gogo proto( https://github.com/gogo/protobuf )を使用して試すことができます。jsontag拡張機能を使用すると、protoメッセージは次のようになります。

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

必要に応じて、さらにタグを追加することもできます。

2

Jsonpbパッケージの下のマーシャラーには、EmitDefaultsフィールドがあります。これをtrueに設定すると、構造体のomitemptyタグが無視されます。

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

1
Sathesh

「sed」コマンドを使用して、次のようなファイルからこのテキストを削除できます

sed -i "" -e "s/,omitempty//g" ./api/proto/*.go

args:

  1. -i ""は同じ名前のファイルを保持することを意味
  2. -e "s/,omitempty//g" = "s/SEARCH/INSERT/g"のように置き換えるフォーマット
1
Maxim

encoding/jsonパッケージをmy_jsonなどの独自のフォルダーにコピーし、 omitEmpty フィールドをfalseに変更し、my_json.Marshal()を使用してstructをjson文字列にエンコードできます。

0
tailnode