Skip to content

Commit ff4dc68

Browse files
abicejohanbrandhorst
authored andcommitted
marshal_jsonpb: Added nil slice default value (#854)
* marshal_jsonpb: Added nil slice default value * marshal_jsonpb: reduced indentation
1 parent a0500cb commit ff4dc68

File tree

4 files changed

+189
-18
lines changed

4 files changed

+189
-18
lines changed

examples/integration/integration_test.go

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,25 +1360,57 @@ func testResponseBodies(t *testing.T, port int) {
13601360
}
13611361

13621362
func testResponseStrings(t *testing.T, port int) {
1363-
url := fmt.Sprintf("http://localhost:%d/responsestrings/foo", port)
1364-
resp, err := http.Get(url)
1365-
if err != nil {
1366-
t.Errorf("http.Get(%q) failed with %v; want success", url, err)
1367-
return
1368-
}
1369-
defer resp.Body.Close()
1370-
buf, err := ioutil.ReadAll(resp.Body)
1371-
if err != nil {
1372-
t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
1373-
return
1374-
}
1363+
ctx, cancel := context.WithCancel(context.Background())
1364+
defer cancel()
1365+
// Run Secondary server with different marshalling
1366+
ch := make(chan error)
1367+
go func() {
1368+
if err := runGateway(ctx, ":8081", runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{EmitDefaults: true})); err != nil {
1369+
ch <- fmt.Errorf("cannot run gateway service: %v", err)
1370+
}
1371+
}()
13751372

1376-
if got, want := resp.StatusCode, http.StatusOK; got != want {
1377-
t.Errorf("resp.StatusCode = %d; want %d", got, want)
1378-
t.Logf("%s", buf)
1379-
}
1373+
port = 8081
13801374

1381-
if got, want := string(buf), `["hello","foo"]`; got != want {
1382-
t.Errorf("response = %q; want %q", got, want)
1375+
for i, spec := range []struct {
1376+
endpoint string
1377+
expectedCode int
1378+
expectedBody string
1379+
}{
1380+
{
1381+
endpoint: fmt.Sprintf("http://localhost:%d/responsestrings/foo", port),
1382+
expectedCode: http.StatusOK,
1383+
expectedBody: `["hello","foo"]`,
1384+
},
1385+
{
1386+
endpoint: fmt.Sprintf("http://localhost:%d/responsestrings/empty", port),
1387+
expectedCode: http.StatusOK,
1388+
expectedBody: `[]`,
1389+
},
1390+
} {
1391+
t.Run(strconv.Itoa(i), func(t *testing.T) {
1392+
url := spec.endpoint
1393+
resp, err := http.Get(url)
1394+
if err != nil {
1395+
t.Errorf("http.Get(%q) failed with %v; want success", url, err)
1396+
return
1397+
}
1398+
defer resp.Body.Close()
1399+
buf, err := ioutil.ReadAll(resp.Body)
1400+
if err != nil {
1401+
t.Errorf("ioutil.ReadAll(resp.Body) failed with %v; want success", err)
1402+
return
1403+
}
1404+
1405+
if got, want := resp.StatusCode, spec.expectedCode; got != want {
1406+
t.Errorf("resp.StatusCode = %d; want %d", got, want)
1407+
t.Logf("%s", buf)
1408+
}
1409+
1410+
if got, want := string(buf), spec.expectedBody; got != want {
1411+
t.Errorf("response = %q; want %q", got, want)
1412+
}
1413+
})
13831414
}
1415+
13841416
}

examples/server/responsebody.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ func (s *responseBodyServer) ListResponseBodies(ctx context.Context, req *exampl
3333
}
3434

3535
func (s *responseBodyServer) ListResponseStrings(ctx context.Context, req *examples.ResponseBodyIn) (*examples.RepeatedResponseStrings, error) {
36+
if req.Data == "empty" {
37+
return &examples.RepeatedResponseStrings{
38+
Values: []string{},
39+
}, nil
40+
}
3641
return &examples.RepeatedResponseStrings{
3742
Values: []string{"hello", req.Data},
3843
}, nil

runtime/marshal_jsonpb.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) {
6767
rv = rv.Elem()
6868
}
6969

70+
if rv.Kind() == reflect.Slice && rv.IsNil() && j.EmitDefaults {
71+
return []byte("[]"), nil
72+
}
73+
7074
if rv.Kind() == reflect.Map {
7175
m := make(map[string]*json.RawMessage)
7276
for _, k := range rv.MapKeys() {

runtime/marshal_jsonpb_test.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package runtime_test
33
import (
44
"bytes"
55
"reflect"
6+
"strconv"
67
"strings"
78
"testing"
89

@@ -614,3 +615,132 @@ var (
614615
// TODO(yugui) Add other well-known types once jsonpb supports them
615616
}
616617
)
618+
619+
func TestJSONPbMarshalResponseBodies(t *testing.T) {
620+
for i, spec := range []struct {
621+
input interface{}
622+
emitDefaults bool
623+
verifier func(json string)
624+
}{
625+
{
626+
input: &examplepb.ResponseBodyOut{
627+
Response: &examplepb.ResponseBodyOut_Response{Data: "abcdef"},
628+
},
629+
verifier: func(json string) {
630+
expected := `{"response":{"data":"abcdef"}}`
631+
if json != expected {
632+
t.Errorf("json not equal (%q, %q)", json, expected)
633+
}
634+
},
635+
},
636+
{
637+
emitDefaults: true,
638+
input: &examplepb.ResponseBodyOut{},
639+
verifier: func(json string) {
640+
expected := `{"response":null}`
641+
if json != expected {
642+
t.Errorf("json not equal (%q, %q)", json, expected)
643+
}
644+
},
645+
},
646+
{
647+
input: &examplepb.RepeatedResponseBodyOut_Response{},
648+
verifier: func(json string) {
649+
expected := `{}`
650+
if json != expected {
651+
t.Errorf("json not equal (%q, %q)", json, expected)
652+
}
653+
},
654+
},
655+
{
656+
emitDefaults: true,
657+
input: &examplepb.RepeatedResponseBodyOut_Response{},
658+
verifier: func(json string) {
659+
expected := `{"data":""}`
660+
if json != expected {
661+
t.Errorf("json not equal (%q, %q)", json, expected)
662+
}
663+
},
664+
},
665+
{
666+
input: ([]*examplepb.RepeatedResponseBodyOut_Response)(nil),
667+
verifier: func(json string) {
668+
expected := `null`
669+
if json != expected {
670+
t.Errorf("json not equal (%q, %q)", json, expected)
671+
}
672+
},
673+
},
674+
{
675+
emitDefaults: true,
676+
input: ([]*examplepb.RepeatedResponseBodyOut_Response)(nil),
677+
verifier: func(json string) {
678+
expected := `[]`
679+
if json != expected {
680+
t.Errorf("json not equal (%q, %q)", json, expected)
681+
}
682+
},
683+
},
684+
{
685+
input: []*examplepb.RepeatedResponseBodyOut_Response{},
686+
verifier: func(json string) {
687+
expected := `[]`
688+
if json != expected {
689+
t.Errorf("json not equal (%q, %q)", json, expected)
690+
}
691+
},
692+
},
693+
{
694+
input: []string{"something"},
695+
verifier: func(json string) {
696+
expected := `["something"]`
697+
if json != expected {
698+
t.Errorf("json not equal (%q, %q)", json, expected)
699+
}
700+
},
701+
},
702+
{
703+
input: []string{},
704+
verifier: func(json string) {
705+
expected := `[]`
706+
if json != expected {
707+
t.Errorf("json not equal (%q, %q)", json, expected)
708+
}
709+
},
710+
},
711+
{
712+
input: ([]string)(nil),
713+
verifier: func(json string) {
714+
expected := `null`
715+
if json != expected {
716+
t.Errorf("json not equal (%q, %q)", json, expected)
717+
}
718+
},
719+
},
720+
{
721+
emitDefaults: true,
722+
input: ([]string)(nil),
723+
verifier: func(json string) {
724+
expected := `[]`
725+
if json != expected {
726+
t.Errorf("json not equal (%q, %q)", json, expected)
727+
}
728+
},
729+
},
730+
} {
731+
732+
t.Run(strconv.Itoa(i), func(t *testing.T) {
733+
m := runtime.JSONPb{
734+
EmitDefaults: spec.emitDefaults,
735+
}
736+
val := spec.input
737+
buf, err := m.Marshal(val)
738+
if err != nil {
739+
t.Errorf("m.Marshal(%v) failed with %v; want success; spec=%v", val, err, spec)
740+
}
741+
if spec.verifier != nil {
742+
spec.verifier(string(buf))
743+
}
744+
})
745+
}
746+
}

0 commit comments

Comments
 (0)