Skip to content

Commit

Permalink
Merge pull request grpc-ecosystem#154 from gengo/feature/oneof-map
Browse files Browse the repository at this point in the history
Add more examples to marshalers
  • Loading branch information
yugui committed May 11, 2016
2 parents ef6e393 + c1af7b0 commit ca3b840
Show file tree
Hide file tree
Showing 4 changed files with 324 additions and 271 deletions.
16 changes: 16 additions & 0 deletions examples/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,22 @@ func testABECreateBody(t *testing.T) {
Amount: 20,
},
},
RepeatedStringValue: []string{"a", "b", "c"},
OneofValue: &gw.ABitOfEverything_OneofString{
OneofString: "x",
},
MapValue: map[string]gw.NumericEnum{
"a": gw.NumericEnum_ONE,
"b": gw.NumericEnum_ZERO,
},
MappedStringValue: map[string]string{
"a": "x",
"b": "y",
},
MappedNestedValue: map[string]*gw.ABitOfEverything_Nested{
"a": {Name: "x", Amount: 1},
"b": {Name: "y", Amount: 2},
},
}
url := "http://localhost:8080/v1/example/a_bit_of_everything"
var m jsonpb.Marshaler
Expand Down
189 changes: 118 additions & 71 deletions runtime/marshal_json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import (

"github.com/gengo/grpc-gateway/examples/examplepb"
"github.com/gengo/grpc-gateway/runtime"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes/empty"
structpb "github.com/golang/protobuf/ptypes/struct"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/golang/protobuf/ptypes/wrappers"
)

func TestJSONBuiltinMarshal(t *testing.T) {
Expand All @@ -31,28 +36,28 @@ func TestJSONBuiltinMarshal(t *testing.T) {
}
}

func TestJSONBuiltinMarshalPrimitive(t *testing.T) {
func TestJSONBuiltinMarshalField(t *testing.T) {
var m runtime.JSONBuiltin
for _, v := range []interface{}{
"",
"foo",
1,
0,
-1,
-0.0,
1.5,
} {
buf, err := m.Marshal(v)
for _, fixt := range builtinFieldFixtures {
buf, err := m.Marshal(fixt.data)
if err != nil {
t.Errorf("m.Marshal(%v) failed with %v; want success", v, err)
t.Errorf("m.Marshal(%v) failed with %v; want success", fixt.data, err)
}
if got, want := string(buf), fixt.json; got != want {
t.Errorf("got = %q; want %q; data = %#v", got, want, fixt.data)
}
}
}

dest := reflect.New(reflect.TypeOf(v))
if err := json.Unmarshal(buf, dest.Interface()); err != nil {
t.Errorf("json.Unmarshal(%q, unmarshaled) failed with %v; want success", buf, err)
func TestJSONBuiltinMarshalFieldKnownErrors(t *testing.T) {
var m runtime.JSONBuiltin
for _, fixt := range builtinKnownErrors {
buf, err := m.Marshal(fixt.data)
if err != nil {
t.Errorf("m.Marshal(%v) failed with %v; want success", fixt.data, err)
}
if got, want := dest.Elem().Interface(), v; !reflect.DeepEqual(got, want) {
t.Errorf("got = %v; want %v", &got, &want)
if got, want := string(buf), fixt.json; got == want {
t.Errorf("surprisingly got = %q; as want %q; data = %#v", got, want, fixt.data)
}
}
}
Expand All @@ -76,27 +81,26 @@ func TestJSONBuiltinsnmarshal(t *testing.T) {
}
}

func TestJSONBuiltinUnmarshalPrimitive(t *testing.T) {
func TestJSONBuiltinUnmarshalField(t *testing.T) {
var m runtime.JSONBuiltin
for _, spec := range []struct {
data string
want interface{}
}{
{data: `""`, want: ""},
{data: `"foo"`, want: "foo"},
{data: `1`, want: 1},
{data: `0`, want: 0},
{data: `-1`, want: -1},
{data: `-0.0`, want: -0.0},
{data: `1.5`, want: 1.5},
} {
dest := reflect.New(reflect.TypeOf(spec.want))
if err := m.Unmarshal([]byte(spec.data), dest.Interface()); err != nil {
t.Errorf("m.Unmarshal(%q, dest) failed with %v; want success", spec.data, err)
for _, fixt := range builtinFieldFixtures {
dest := reflect.New(reflect.TypeOf(fixt.data))
if err := m.Unmarshal([]byte(fixt.json), dest.Interface()); err != nil {
t.Errorf("m.Unmarshal(%q, dest) failed with %v; want success", fixt.json, err)
}

if got, want := dest.Elem().Interface(), fixt.data; !reflect.DeepEqual(got, want) {
t.Errorf("got = %#v; want = %#v; input = %q", got, want, fixt.json)
}
}
}

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

func TestJSONBuiltinEncoderPrimitive(t *testing.T) {
func TestJSONBuiltinEncoderFields(t *testing.T) {
var m runtime.JSONBuiltin
for _, v := range []interface{}{
"",
"foo",
1,
0,
-1,
-0.0,
1.5,
} {
for _, fixt := range builtinFieldFixtures {
var buf bytes.Buffer
enc := m.NewEncoder(&buf)
if err := enc.Encode(v); err != nil {
t.Errorf("enc.Encode(%v) failed with %v; want success", v, err)
if err := enc.Encode(fixt.data); err != nil {
t.Errorf("enc.Encode(%#v) failed with %v; want success", fixt.data, err)
}

dest := reflect.New(reflect.TypeOf(v))
if err := json.Unmarshal(buf.Bytes(), dest.Interface()); err != nil {
t.Errorf("json.Unmarshal(%q, unmarshaled) failed with %v; want success", buf.String(), err)
}
if got, want := dest.Elem().Interface(), v; !reflect.DeepEqual(got, want) {
t.Errorf("got = %v; want %v", &got, &want)
if got, want := buf.String(), fixt.json+"\n"; got != want {
t.Errorf("got = %q; want %q; data = %#v", got, want, fixt.data)
}
}
}
Expand All @@ -170,29 +162,84 @@ func TestJSONBuiltinDecoder(t *testing.T) {
}
}

func TestJSONBuiltinDecoderPrimitive(t *testing.T) {
func TestJSONBuiltinDecoderFields(t *testing.T) {
var m runtime.JSONBuiltin
for _, spec := range []struct {
data string
want interface{}
}{
{data: `""`, want: ""},
{data: `"foo"`, want: "foo"},
{data: `1`, want: 1},
{data: `0`, want: 0},
{data: `-1`, want: -1},
{data: `-0.0`, want: -0.0},
{data: `1.5`, want: 1.5},
} {
r := strings.NewReader(spec.data)
for _, fixt := range builtinFieldFixtures {
r := strings.NewReader(fixt.json)
dec := m.NewDecoder(r)
dest := reflect.New(reflect.TypeOf(spec.want))
dest := reflect.New(reflect.TypeOf(fixt.data))
if err := dec.Decode(dest.Interface()); err != nil {
t.Errorf("dec.Decode(dest) failed with %v; want success; data=%q", err, spec.data)
t.Errorf("dec.Decode(dest) failed with %v; want success; data = %q", err, fixt.json)
}

if got, want := dest.Elem().Interface(), spec.want; !reflect.DeepEqual(got, want) {
t.Errorf("got = %v; want = %v", got, want)
if got, want := dest.Elem().Interface(), fixt.data; !reflect.DeepEqual(got, want) {
t.Errorf("got = %v; want = %v; input = %q", got, want, fixt.json)
}
}
}

var (
builtinFieldFixtures = []struct {
data interface{}
json string
}{
{data: "", json: `""`},
{data: proto.String(""), json: `""`},
{data: "foo", json: `"foo"`},
{data: proto.String("foo"), json: `"foo"`},
{data: int32(-1), json: "-1"},
{data: proto.Int32(-1), json: "-1"},
{data: int64(-1), json: "-1"},
{data: proto.Int64(-1), json: "-1"},
{data: uint32(123), json: "123"},
{data: proto.Uint32(123), json: "123"},
{data: uint64(123), json: "123"},
{data: proto.Uint64(123), json: "123"},
{data: float32(-1.5), json: "-1.5"},
{data: proto.Float32(-1.5), json: "-1.5"},
{data: float64(-1.5), json: "-1.5"},
{data: proto.Float64(-1.5), json: "-1.5"},
{data: true, json: "true"},
{data: proto.Bool(true), json: "true"},
{data: (*string)(nil), json: "null"},
{data: new(empty.Empty), json: "{}"},
{data: examplepb.NumericEnum_ONE, json: "1"},
{
data: (*examplepb.NumericEnum)(proto.Int32(int32(examplepb.NumericEnum_ONE))),
json: "1",
},
}
builtinKnownErrors = []struct {
data interface{}
json string
}{
{data: examplepb.NumericEnum_ONE, json: "ONE"},
{
data: (*examplepb.NumericEnum)(proto.Int32(int32(examplepb.NumericEnum_ONE))),
json: "ONE",
},
{
data: &examplepb.ABitOfEverything_OneofString{OneofString: "abc"},
json: `"abc"`,
},
{
data: &timestamp.Timestamp{
Seconds: 1462875553,
Nanos: 123000000,
},
json: `"2016-05-10T10:19:13.123Z"`,
},
{
data: &wrappers.Int32Value{Value: 123},
json: "123",
},
{
data: &structpb.Value{
Kind: &structpb.Value_StringValue{
StringValue: "abc",
},
},
json: `"abc"`,
},
}
)
5 changes: 5 additions & 0 deletions runtime/marshal_jsonpb.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ func decodeNonProtoField(d *json.Decoder, v interface{}) error {
if rv.IsNil() {
rv.Set(reflect.New(rv.Type().Elem()))
}
if rv.Type().ConvertibleTo(typeProtoMessage) {
return jsonpb.UnmarshalNext(d, rv.Interface().(proto.Message))
}
rv = rv.Elem()
}
if rv.Kind() == reflect.Map {
Expand Down Expand Up @@ -196,3 +199,5 @@ type protoEnum interface {
fmt.Stringer
EnumDescriptor() ([]byte, []int)
}

var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
Loading

0 comments on commit ca3b840

Please sign in to comment.