From 7d304729b4cf9949a345fec4423fcb7f1c7e43af Mon Sep 17 00:00:00 2001 From: Stephan Renatus Date: Mon, 5 Feb 2018 16:52:29 +0100 Subject: [PATCH] make jsonpb marshaler emit defaults (#3) add `-emit-defaults` flag so that output will include default values (e.g. "false" for boolean flags) --- cmd/grpcurl/grpcurl.go | 13 +++++++++++-- grpcurl.go | 33 +++++---------------------------- grpcurl_test.go | 9 +++++++-- 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/cmd/grpcurl/grpcurl.go b/cmd/grpcurl/grpcurl.go index 28603ef..be24759 100644 --- a/cmd/grpcurl/grpcurl.go +++ b/cmd/grpcurl/grpcurl.go @@ -12,6 +12,8 @@ import ( "strings" "time" + "github.com/golang/protobuf/jsonpb" + "github.com/golang/protobuf/proto" "github.com/jhump/protoreflect/desc" "github.com/jhump/protoreflect/grpcreflect" "golang.org/x/net/context" @@ -64,6 +66,8 @@ var ( `The maximum total time the operation can take. This is useful for preventing batch jobs that use grpcurl from hanging due to slow or bad network links or due to incorrect stream method usage.`) + emitDefaults = flag.Bool("emit-defaults", false, + `Emit default values from JSON-encoded responses.`) verbose = flag.Bool("v", false, `Enable verbose output.`) ) @@ -442,12 +446,17 @@ func (*handler) OnReceiveHeaders(md metadata.MD) { } } -func (h *handler) OnReceiveResponse(rsp json.RawMessage) { +func (h *handler) OnReceiveResponse(resp proto.Message) { h.respCount++ if *verbose { fmt.Print("\nResponse contents:\n") } - fmt.Println(string(rsp)) + jsm := jsonpb.Marshaler{EmitDefaults: *emitDefaults, Indent: " "} + respStr, err := jsm.MarshalToString(resp) + if err != nil { + fail(err, "failed to generate JSON form of response message") + } + fmt.Println(respStr) } func (h *handler) OnReceiveTrailers(stat *status.Status, md metadata.MD) { diff --git a/grpcurl.go b/grpcurl.go index e691348..018f72b 100644 --- a/grpcurl.go +++ b/grpcurl.go @@ -263,7 +263,7 @@ type InvocationEventHandler interface { // OnReceiveHeaders is called when response headers have been received. OnReceiveHeaders(metadata.MD) // OnReceiveResponse is called for each response message received. - OnReceiveResponse(json.RawMessage) + OnReceiveResponse(proto.Message) // OnReceiveTrailers is called when response trailers and final RPC status have been received. OnReceiveTrailers(*status.Status, metadata.MD) } @@ -384,14 +384,8 @@ func invokeUnary(ctx context.Context, stub grpcdynamic.Stub, md *desc.MethodDesc handler.OnReceiveHeaders(respHeaders) - var respStr string if stat.Code() == codes.OK { - jsm := jsonpb.Marshaler{Indent: " "} - respStr, err = jsm.MarshalToString(resp) - if err != nil { - return fmt.Errorf("failed to generate JSON form of response message: %v", err) - } - handler.OnReceiveResponse(json.RawMessage(respStr)) + handler.OnReceiveResponse(resp) } handler.OnReceiveTrailers(stat, respTrailers) @@ -447,14 +441,8 @@ func invokeClientStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met handler.OnReceiveHeaders(respHeaders) } - var respStr string if stat.Code() == codes.OK { - jsm := jsonpb.Marshaler{Indent: " "} - respStr, err = jsm.MarshalToString(resp) - if err != nil { - return fmt.Errorf("failed to generate JSON form of response message: %v", err) - } - handler.OnReceiveResponse(json.RawMessage(respStr)) + handler.OnReceiveResponse(resp) } handler.OnReceiveTrailers(stat, str.Trailer()) @@ -502,12 +490,7 @@ func invokeServerStream(ctx context.Context, stub grpcdynamic.Stub, md *desc.Met } break } - jsm := jsonpb.Marshaler{Indent: " "} - respStr, err := jsm.MarshalToString(resp) - if err != nil { - return fmt.Errorf("failed to generate JSON form of response message: %v", err) - } - handler.OnReceiveResponse(json.RawMessage(respStr)) + handler.OnReceiveResponse(resp) } stat, ok := status.FromError(err) @@ -588,13 +571,7 @@ func invokeBidi(ctx context.Context, cancel context.CancelFunc, stub grpcdynamic } break } - jsm := jsonpb.Marshaler{Indent: " "} - respStr, err := jsm.MarshalToString(resp) - if err != nil { - return fmt.Errorf("failed to generate JSON form of response message: %v", err) - } - - handler.OnReceiveResponse(json.RawMessage(respStr)) + handler.OnReceiveResponse(resp) } if se, ok := sendErr.Load().(error); ok && se != io.EOF { diff --git a/grpcurl_test.go b/grpcurl_test.go index 13613b7..4e373f8 100644 --- a/grpcurl_test.go +++ b/grpcurl_test.go @@ -576,8 +576,13 @@ func (h *handler) OnReceiveHeaders(md metadata.MD) { h.respHeaders = md } -func (h *handler) OnReceiveResponse(msg json.RawMessage) { - h.respMessages = append(h.respMessages, string(msg)) +func (h *handler) OnReceiveResponse(msg proto.Message) { + jsm := jsonpb.Marshaler{Indent: " "} + respStr, err := jsm.MarshalToString(msg) + if err != nil { + panic(fmt.Errorf("failed to generate JSON form of response message: %v", err)) + } + h.respMessages = append(h.respMessages, respStr) } func (h *handler) OnReceiveTrailers(stat *status.Status, md metadata.MD) {