Skip to content

Commit

Permalink
Implement support for anonymous contained structs by extracting
Browse files Browse the repository at this point in the history
defaultResolveStruct from DefaultResolveFn
  • Loading branch information
Ariel Salomon authored and chris-ramon committed Jul 28, 2018
1 parent 69ba795 commit d376817
Showing 1 changed file with 33 additions and 26 deletions.
59 changes: 33 additions & 26 deletions executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,38 @@ type FieldResolver interface {
Resolve(p ResolveParams) (interface{}, error)
}

func defaultResolveStruct(sourceVal reflect.Value, fieldName string) (interface{}, error) {
for i := 0; i < sourceVal.NumField(); i++ {
valueField := sourceVal.Field(i)
typeField := sourceVal.Type().Field(i)
// try matching the field name first
if strings.EqualFold(typeField.Name, fieldName) {
return valueField.Interface(), nil
}
if typeField.Anonymous && typeField.Type.Kind() == reflect.Struct {
return defaultResolveStruct(valueField, fieldName)
}
tag := typeField.Tag
checkTag := func(tagName string) bool {
t := tag.Get(tagName)
tOptions := strings.Split(t, ",")
if len(tOptions) == 0 {
return false
}
if tOptions[0] != fieldName {
return false
}
return true
}
if checkTag("json") || checkTag("graphql") {
return valueField.Interface(), nil
} else {
continue
}
}
return nil, nil
}

// defaultResolveFn If a resolve function is not given, then a default resolve behavior is used
// which takes the property of the source object of the same name as the field
// and returns it as the result, or if it's a function, returns the result
Expand All @@ -798,32 +830,7 @@ func DefaultResolveFn(p ResolveParams) (interface{}, error) {
}

if sourceVal.Type().Kind() == reflect.Struct {
for i := 0; i < sourceVal.NumField(); i++ {
valueField := sourceVal.Field(i)
typeField := sourceVal.Type().Field(i)
// try matching the field name first
if strings.EqualFold(typeField.Name, p.Info.FieldName) {
return valueField.Interface(), nil
}
tag := typeField.Tag
checkTag := func(tagName string) bool {
t := tag.Get(tagName)
tOptions := strings.Split(t, ",")
if len(tOptions) == 0 {
return false
}
if tOptions[0] != p.Info.FieldName {
return false
}
return true
}
if checkTag("json") || checkTag("graphql") {
return valueField.Interface(), nil
} else {
continue
}
}
return nil, nil
return defaultResolveStruct(sourceVal, p.Info.FieldName)
}

// try p.Source as a map[string]interface
Expand Down

0 comments on commit d376817

Please sign in to comment.