Skip to content

Commit ab4f1c2

Browse files
committed
Merge pull request #154 from gengo/feature/oneof-map
Add more examples to marshalers
2 parents ee8f8cb + b8ca34c commit ab4f1c2

File tree

4 files changed

+324
-271
lines changed

4 files changed

+324
-271
lines changed

examples/integration_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,22 @@ func testABECreateBody(t *testing.T) {
238238
Amount: 20,
239239
},
240240
},
241+
RepeatedStringValue: []string{"a", "b", "c"},
242+
OneofValue: &gw.ABitOfEverything_OneofString{
243+
OneofString: "x",
244+
},
245+
MapValue: map[string]gw.NumericEnum{
246+
"a": gw.NumericEnum_ONE,
247+
"b": gw.NumericEnum_ZERO,
248+
},
249+
MappedStringValue: map[string]string{
250+
"a": "x",
251+
"b": "y",
252+
},
253+
MappedNestedValue: map[string]*gw.ABitOfEverything_Nested{
254+
"a": {Name: "x", Amount: 1},
255+
"b": {Name: "y", Amount: 2},
256+
},
241257
}
242258
url := "http://localhost:8080/v1/example/a_bit_of_everything"
243259
var m jsonpb.Marshaler

runtime/marshal_json_test.go

Lines changed: 118 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ import (
99

1010
"github.com/gengo/grpc-gateway/examples/examplepb"
1111
"github.com/gengo/grpc-gateway/runtime"
12+
"github.com/golang/protobuf/proto"
13+
"github.com/golang/protobuf/ptypes/empty"
14+
structpb "github.com/golang/protobuf/ptypes/struct"
15+
"github.com/golang/protobuf/ptypes/timestamp"
16+
"github.com/golang/protobuf/ptypes/wrappers"
1217
)
1318

1419
func TestJSONBuiltinMarshal(t *testing.T) {
@@ -31,28 +36,28 @@ func TestJSONBuiltinMarshal(t *testing.T) {
3136
}
3237
}
3338

34-
func TestJSONBuiltinMarshalPrimitive(t *testing.T) {
39+
func TestJSONBuiltinMarshalField(t *testing.T) {
3540
var m runtime.JSONBuiltin
36-
for _, v := range []interface{}{
37-
"",
38-
"foo",
39-
1,
40-
0,
41-
-1,
42-
-0.0,
43-
1.5,
44-
} {
45-
buf, err := m.Marshal(v)
41+
for _, fixt := range builtinFieldFixtures {
42+
buf, err := m.Marshal(fixt.data)
4643
if err != nil {
47-
t.Errorf("m.Marshal(%v) failed with %v; want success", v, err)
44+
t.Errorf("m.Marshal(%v) failed with %v; want success", fixt.data, err)
4845
}
46+
if got, want := string(buf), fixt.json; got != want {
47+
t.Errorf("got = %q; want %q; data = %#v", got, want, fixt.data)
48+
}
49+
}
50+
}
4951

50-
dest := reflect.New(reflect.TypeOf(v))
51-
if err := json.Unmarshal(buf, dest.Interface()); err != nil {
52-
t.Errorf("json.Unmarshal(%q, unmarshaled) failed with %v; want success", buf, err)
52+
func TestJSONBuiltinMarshalFieldKnownErrors(t *testing.T) {
53+
var m runtime.JSONBuiltin
54+
for _, fixt := range builtinKnownErrors {
55+
buf, err := m.Marshal(fixt.data)
56+
if err != nil {
57+
t.Errorf("m.Marshal(%v) failed with %v; want success", fixt.data, err)
5358
}
54-
if got, want := dest.Elem().Interface(), v; !reflect.DeepEqual(got, want) {
55-
t.Errorf("got = %v; want %v", &got, &want)
59+
if got, want := string(buf), fixt.json; got == want {
60+
t.Errorf("surprisingly got = %q; as want %q; data = %#v", got, want, fixt.data)
5661
}
5762
}
5863
}
@@ -76,27 +81,26 @@ func TestJSONBuiltinsnmarshal(t *testing.T) {
7681
}
7782
}
7883

79-
func TestJSONBuiltinUnmarshalPrimitive(t *testing.T) {
84+
func TestJSONBuiltinUnmarshalField(t *testing.T) {
8085
var m runtime.JSONBuiltin
81-
for _, spec := range []struct {
82-
data string
83-
want interface{}
84-
}{
85-
{data: `""`, want: ""},
86-
{data: `"foo"`, want: "foo"},
87-
{data: `1`, want: 1},
88-
{data: `0`, want: 0},
89-
{data: `-1`, want: -1},
90-
{data: `-0.0`, want: -0.0},
91-
{data: `1.5`, want: 1.5},
92-
} {
93-
dest := reflect.New(reflect.TypeOf(spec.want))
94-
if err := m.Unmarshal([]byte(spec.data), dest.Interface()); err != nil {
95-
t.Errorf("m.Unmarshal(%q, dest) failed with %v; want success", spec.data, err)
86+
for _, fixt := range builtinFieldFixtures {
87+
dest := reflect.New(reflect.TypeOf(fixt.data))
88+
if err := m.Unmarshal([]byte(fixt.json), dest.Interface()); err != nil {
89+
t.Errorf("m.Unmarshal(%q, dest) failed with %v; want success", fixt.json, err)
90+
}
91+
92+
if got, want := dest.Elem().Interface(), fixt.data; !reflect.DeepEqual(got, want) {
93+
t.Errorf("got = %#v; want = %#v; input = %q", got, want, fixt.json)
9694
}
95+
}
96+
}
9797

98-
if got, want := dest.Elem().Interface(), spec.want; !reflect.DeepEqual(got, want) {
99-
t.Errorf("got = %v; want = %v", got, want)
98+
func TestJSONBuiltinUnmarshalFieldKnownErrors(t *testing.T) {
99+
var m runtime.JSONBuiltin
100+
for _, fixt := range builtinKnownErrors {
101+
dest := reflect.New(reflect.TypeOf(fixt.data))
102+
if err := m.Unmarshal([]byte(fixt.json), dest.Interface()); err == nil {
103+
t.Errorf("m.Unmarshal(%q, dest) succeeded; want ane error", fixt.json)
100104
}
101105
}
102106
}
@@ -122,29 +126,17 @@ func TestJSONBuiltinEncoder(t *testing.T) {
122126
}
123127
}
124128

125-
func TestJSONBuiltinEncoderPrimitive(t *testing.T) {
129+
func TestJSONBuiltinEncoderFields(t *testing.T) {
126130
var m runtime.JSONBuiltin
127-
for _, v := range []interface{}{
128-
"",
129-
"foo",
130-
1,
131-
0,
132-
-1,
133-
-0.0,
134-
1.5,
135-
} {
131+
for _, fixt := range builtinFieldFixtures {
136132
var buf bytes.Buffer
137133
enc := m.NewEncoder(&buf)
138-
if err := enc.Encode(v); err != nil {
139-
t.Errorf("enc.Encode(%v) failed with %v; want success", v, err)
134+
if err := enc.Encode(fixt.data); err != nil {
135+
t.Errorf("enc.Encode(%#v) failed with %v; want success", fixt.data, err)
140136
}
141137

142-
dest := reflect.New(reflect.TypeOf(v))
143-
if err := json.Unmarshal(buf.Bytes(), dest.Interface()); err != nil {
144-
t.Errorf("json.Unmarshal(%q, unmarshaled) failed with %v; want success", buf.String(), err)
145-
}
146-
if got, want := dest.Elem().Interface(), v; !reflect.DeepEqual(got, want) {
147-
t.Errorf("got = %v; want %v", &got, &want)
138+
if got, want := buf.String(), fixt.json+"\n"; got != want {
139+
t.Errorf("got = %q; want %q; data = %#v", got, want, fixt.data)
148140
}
149141
}
150142
}
@@ -170,29 +162,84 @@ func TestJSONBuiltinDecoder(t *testing.T) {
170162
}
171163
}
172164

173-
func TestJSONBuiltinDecoderPrimitive(t *testing.T) {
165+
func TestJSONBuiltinDecoderFields(t *testing.T) {
174166
var m runtime.JSONBuiltin
175-
for _, spec := range []struct {
176-
data string
177-
want interface{}
178-
}{
179-
{data: `""`, want: ""},
180-
{data: `"foo"`, want: "foo"},
181-
{data: `1`, want: 1},
182-
{data: `0`, want: 0},
183-
{data: `-1`, want: -1},
184-
{data: `-0.0`, want: -0.0},
185-
{data: `1.5`, want: 1.5},
186-
} {
187-
r := strings.NewReader(spec.data)
167+
for _, fixt := range builtinFieldFixtures {
168+
r := strings.NewReader(fixt.json)
188169
dec := m.NewDecoder(r)
189-
dest := reflect.New(reflect.TypeOf(spec.want))
170+
dest := reflect.New(reflect.TypeOf(fixt.data))
190171
if err := dec.Decode(dest.Interface()); err != nil {
191-
t.Errorf("dec.Decode(dest) failed with %v; want success; data=%q", err, spec.data)
172+
t.Errorf("dec.Decode(dest) failed with %v; want success; data = %q", err, fixt.json)
192173
}
193174

194-
if got, want := dest.Elem().Interface(), spec.want; !reflect.DeepEqual(got, want) {
195-
t.Errorf("got = %v; want = %v", got, want)
175+
if got, want := dest.Elem().Interface(), fixt.data; !reflect.DeepEqual(got, want) {
176+
t.Errorf("got = %v; want = %v; input = %q", got, want, fixt.json)
196177
}
197178
}
198179
}
180+
181+
var (
182+
builtinFieldFixtures = []struct {
183+
data interface{}
184+
json string
185+
}{
186+
{data: "", json: `""`},
187+
{data: proto.String(""), json: `""`},
188+
{data: "foo", json: `"foo"`},
189+
{data: proto.String("foo"), json: `"foo"`},
190+
{data: int32(-1), json: "-1"},
191+
{data: proto.Int32(-1), json: "-1"},
192+
{data: int64(-1), json: "-1"},
193+
{data: proto.Int64(-1), json: "-1"},
194+
{data: uint32(123), json: "123"},
195+
{data: proto.Uint32(123), json: "123"},
196+
{data: uint64(123), json: "123"},
197+
{data: proto.Uint64(123), json: "123"},
198+
{data: float32(-1.5), json: "-1.5"},
199+
{data: proto.Float32(-1.5), json: "-1.5"},
200+
{data: float64(-1.5), json: "-1.5"},
201+
{data: proto.Float64(-1.5), json: "-1.5"},
202+
{data: true, json: "true"},
203+
{data: proto.Bool(true), json: "true"},
204+
{data: (*string)(nil), json: "null"},
205+
{data: new(empty.Empty), json: "{}"},
206+
{data: examplepb.NumericEnum_ONE, json: "1"},
207+
{
208+
data: (*examplepb.NumericEnum)(proto.Int32(int32(examplepb.NumericEnum_ONE))),
209+
json: "1",
210+
},
211+
}
212+
builtinKnownErrors = []struct {
213+
data interface{}
214+
json string
215+
}{
216+
{data: examplepb.NumericEnum_ONE, json: "ONE"},
217+
{
218+
data: (*examplepb.NumericEnum)(proto.Int32(int32(examplepb.NumericEnum_ONE))),
219+
json: "ONE",
220+
},
221+
{
222+
data: &examplepb.ABitOfEverything_OneofString{OneofString: "abc"},
223+
json: `"abc"`,
224+
},
225+
{
226+
data: &timestamp.Timestamp{
227+
Seconds: 1462875553,
228+
Nanos: 123000000,
229+
},
230+
json: `"2016-05-10T10:19:13.123Z"`,
231+
},
232+
{
233+
data: &wrappers.Int32Value{Value: 123},
234+
json: "123",
235+
},
236+
{
237+
data: &structpb.Value{
238+
Kind: &structpb.Value_StringValue{
239+
StringValue: "abc",
240+
},
241+
},
242+
json: `"abc"`,
243+
},
244+
}
245+
)

runtime/marshal_jsonpb.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ func decodeNonProtoField(d *json.Decoder, v interface{}) error {
144144
if rv.IsNil() {
145145
rv.Set(reflect.New(rv.Type().Elem()))
146146
}
147+
if rv.Type().ConvertibleTo(typeProtoMessage) {
148+
return jsonpb.UnmarshalNext(d, rv.Interface().(proto.Message))
149+
}
147150
rv = rv.Elem()
148151
}
149152
if rv.Kind() == reflect.Map {
@@ -196,3 +199,5 @@ type protoEnum interface {
196199
fmt.Stringer
197200
EnumDescriptor() ([]byte, []int)
198201
}
202+
203+
var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()

0 commit comments

Comments
 (0)