Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle JSON tags correctly #141

Merged
merged 1 commit into from
Jul 5, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion dsl/matcher.go
Original file line number Diff line number Diff line change
@@ -299,7 +299,11 @@ func match(srcType reflect.Type, params params) Matcher {

for i := 0; i < srcType.NumField(); i++ {
field := srcType.Field(i)
result[field.Tag.Get("json")] = match(field.Type, pluckParams(field.Type, field.Tag.Get("pact")))
fieldName := getJsonFieldName(field)
if fieldName == "" {
continue
}
result[fieldName] = match(field.Type, pluckParams(field.Type, field.Tag.Get("pact")))
}
return result
case reflect.String:
@@ -332,6 +336,24 @@ func match(srcType reflect.Type, params params) Matcher {
}
}

// getJsonFieldName retrieves the name for a JSON field as
// https://golang.org/pkg/encoding/json/#Marshal would do.
func getJsonFieldName(field reflect.StructField) string {
jsonTag := field.Tag.Get("json")
if jsonTag == "" {
return field.Name
}
// Field should be ignored according to the JSON marshal documentation.
if jsonTag == "-" {
return ""
}
commaIndex := strings.Index(jsonTag, ",")
if commaIndex > -1 {
return jsonTag[:commaIndex]
}
return jsonTag
}

// params are plucked from 'pact' struct tags as match() traverses
// struct fields. They are passed back into match() along with their
// associated type to serve as parameters for the dsl functions.
51 changes: 51 additions & 0 deletions dsl/matcher_test.go
Original file line number Diff line number Diff line change
@@ -570,6 +570,20 @@ func TestMatch(t *testing.T) {
Integer int `json:"integer" pact:"example=42"`
Float float32 `json:"float" pact:"example=6.66"`
}
type jsonTagOmitemptyDTO struct {
Word string `json:"word,omitempty"`
}
type jsonTagMissingDTO struct {
Word string
}
type jsonTagIgnoreFieldDTO struct {
Word string `json:"word"`
Ignored string `json:"-"`
}
type jsonTagDashDTO struct {
Word string `json:"word"`
WordDash string `json:"-,"`
}
str := "str"
type args struct {
src interface{}
@@ -648,6 +662,43 @@ func TestMatch(t *testing.T) {
"float": Like(float32(6.66)),
},
},
{
name: "recursive case - struct with json tag including omitempty",
args: args{
src: jsonTagOmitemptyDTO{},
},
want: StructMatcher{
"word": Like("string"),
},
},
{
name: "recursive case - struct without json tag",
args: args{
src: jsonTagMissingDTO{},
},
want: StructMatcher{
"Word": Like("string"),
},
},
{
name: "recursive case - struct with ignored field",
args: args{
src: jsonTagIgnoreFieldDTO{},
},
want: StructMatcher{
"word": Like("string"),
},
},
{
name: "recursive case - struct with field named '-'",
args: args{
src: jsonTagDashDTO{},
},
want: StructMatcher{
"word": Like("string"),
"-": Like("string"),
},
},
{
name: "base case - string",
args: args{