Skip to content

Commit

Permalink
Add json:".." tags to generated structs
Browse files Browse the repository at this point in the history
Resolves #77
  • Loading branch information
abhinav committed Apr 6, 2016
1 parent 0034f4b commit ee1689e
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 73 deletions.
26 changes: 22 additions & 4 deletions gen/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@

package gen

import "github.com/thriftrw/thriftrw-go/compile"
import (
"fmt"

"github.com/thriftrw/thriftrw-go/compile"
)

// fieldGroupGenerator is responsible for generating code for FieldGroups.
type fieldGroupGenerator struct {
Expand Down Expand Up @@ -53,12 +57,26 @@ func (f fieldGroupGenerator) DefineStruct(g Generator) error {
`type <.Name> struct {
<range .Fields>
<if .Required>
<goCase .Name> <typeReference .Type>
<goCase .Name> <typeReference .Type> <tag .>
<else>
<goCase .Name> <typeReferencePtr .Type>
<goCase .Name> <typeReferencePtr .Type> <tag .>
<end>
<end>
}`, f)
}`,
f,
TemplateFunc("tag", func(f *compile.FieldSpec) string {
// We want to add omitempty if the field is a struct or if it's an
// optional primitive so that we don't have "null" noise in the
// output. Note that binary is not a primitive.

if isStructType(f.Type) || (isPrimitiveType(f.Type) && !f.Required) {
return fmt.Sprintf("`json:\"%s,omitempty\"`", f.Name)
}

return fmt.Sprintf("`json:\"%s\"`", f.Name)
// TODO(abg): Take go.tag and js.name annotations into account
}),
)
}

func (f fieldGroupGenerator) ToWire(g Generator) error {
Expand Down
96 changes: 96 additions & 0 deletions gen/struct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
package gen

import (
"encoding/json"
"fmt"
"reflect"
"testing"

tc "github.com/thriftrw/thriftrw-go/gen/testdata/containers"
Expand Down Expand Up @@ -677,3 +679,97 @@ func TestEmptyException(t *testing.T) {
assert.Equal(t, x, y)
}
}

func TestStructJSON(t *testing.T) {
tests := []struct {
v interface{}
j string
}{
{&ts.Point{X: 0, Y: 0}, `{"x":0,"y":0}`},
{&ts.Point{X: 1, Y: 2}, `{"x":1,"y":2}`},
{&ts.User{Name: ""}, `{"name":""}`},
{&ts.User{Name: "foo"}, `{"name":"foo"}`},
{
&ts.User{
Name: "foo",
Contact: &ts.ContactInfo{EmailAddress: "bar@example.com"},
},
`{"name":"foo","contact":{"emailAddress":"bar@example.com"}}`,
},
{
&ts.User{
Name: "foo",
Contact: &ts.ContactInfo{EmailAddress: ""},
},
`{"name":"foo","contact":{"emailAddress":""}}`,
},
{&tu.EmptyUnion{}, "{}"},
{&tu.Document{Pdf: td.Pdf("hello")}, `{"pdf":"aGVsbG8="}`},
{&tu.Document{Pdf: td.Pdf{}}, `{"pdf":""}`},
{
&tu.Document{PlainText: stringp("hello")},
`{"pdf":null,"plainText":"hello"}`,
},
{&tu.Document{PlainText: stringp("")}, `{"pdf":null,"plainText":""}`},
{
&tu.ArbitraryValue{BoolValue: boolp(true)},
`{"boolValue":true,"listValue":null,"mapValue":null}`,
},
{
&tu.ArbitraryValue{BoolValue: boolp(false)},
`{"boolValue":false,"listValue":null,"mapValue":null}`,
},
{
&tu.ArbitraryValue{Int64Value: int64p(42)},
`{"int64Value":42,"listValue":null,"mapValue":null}`,
},
{
&tu.ArbitraryValue{Int64Value: int64p(0)},
`{"int64Value":0,"listValue":null,"mapValue":null}`,
},
{
&tu.ArbitraryValue{StringValue: stringp("foo")},
`{"stringValue":"foo","listValue":null,"mapValue":null}`,
},
{
&tu.ArbitraryValue{StringValue: stringp("")},
`{"stringValue":"","listValue":null,"mapValue":null}`,
},
{
&tu.ArbitraryValue{ListValue: []*tu.ArbitraryValue{
{BoolValue: boolp(true)},
{Int64Value: int64p(42)},
{StringValue: stringp("foo")},
}},
`{"listValue":[` +
`{"boolValue":true,"listValue":null,"mapValue":null},` +
`{"int64Value":42,"listValue":null,"mapValue":null},` +
`{"stringValue":"foo","listValue":null,"mapValue":null}` +
`],"mapValue":null}`,
},
{
&tu.ArbitraryValue{MapValue: map[string]*tu.ArbitraryValue{
"bool": {BoolValue: boolp(true)},
"int64": {Int64Value: int64p(42)},
"string": {StringValue: stringp("foo")},
}},
`{"listValue":null,"mapValue":{` +
`"bool":{"boolValue":true,"listValue":null,"mapValue":null},` +
`"int64":{"int64Value":42,"listValue":null,"mapValue":null},` +
`"string":{"stringValue":"foo","listValue":null,"mapValue":null}` +
`}}`,
},
}

for _, tt := range tests {
encoded, err := json.Marshal(tt.v)
if assert.NoError(t, err, "failed to JSON encode %v", tt.v) {
assert.Equal(t, tt.j, string(encoded))
}

v := reflect.New(reflect.TypeOf(tt.v).Elem()).Interface()
if assert.NoError(t, json.Unmarshal([]byte(tt.j), v), "failed to decode %q", tt.j) {
assert.Equal(t, tt.v, v)
}
}
}
24 changes: 12 additions & 12 deletions gen/testdata/containers/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion gen/testdata/enums/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion gen/testdata/exceptions/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions gen/testdata/services/service/keyvalue/deletevalue.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions gen/testdata/services/service/keyvalue/getmanyvalues.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions gen/testdata/services/service/keyvalue/getvalue.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions gen/testdata/services/service/keyvalue/setvalue.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion gen/testdata/services/service/keyvalue/size.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion gen/testdata/services/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ee1689e

Please sign in to comment.