Skip to content

Commit 459c4e2

Browse files
author
Ariel Salomon
committed
Implement support for anonymous contained structs by extracting
defaultResolveStruct from DefaultResolveFn
1 parent 0861000 commit 459c4e2

File tree

1 file changed

+33
-26
lines changed

1 file changed

+33
-26
lines changed

executor.go

+33-26
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,38 @@ func defaultResolveTypeFn(p ResolveTypeParams, abstractType Abstract) *Object {
821821
return nil
822822
}
823823

824+
func defaultResolveStruct(sourceVal reflect.Value, fieldName string) (interface{}, error) {
825+
for i := 0; i < sourceVal.NumField(); i++ {
826+
valueField := sourceVal.Field(i)
827+
typeField := sourceVal.Type().Field(i)
828+
// try matching the field name first
829+
if typeField.Name == fieldName {
830+
return valueField.Interface(), nil
831+
}
832+
if typeField.Anonymous && typeField.Type.Kind() == reflect.Struct {
833+
return defaultResolveStruct(valueField, fieldName)
834+
}
835+
tag := typeField.Tag
836+
checkTag := func(tagName string) bool {
837+
t := tag.Get(tagName)
838+
tOptions := strings.Split(t, ",")
839+
if len(tOptions) == 0 {
840+
return false
841+
}
842+
if tOptions[0] != fieldName {
843+
return false
844+
}
845+
return true
846+
}
847+
if checkTag("json") || checkTag("graphql") {
848+
return valueField.Interface(), nil
849+
} else {
850+
continue
851+
}
852+
}
853+
return nil, nil
854+
}
855+
824856
// defaultResolveFn If a resolve function is not given, then a default resolve behavior is used
825857
// which takes the property of the source object of the same name as the field
826858
// and returns it as the result, or if it's a function, returns the result
@@ -835,32 +867,7 @@ func DefaultResolveFn(p ResolveParams) (interface{}, error) {
835867
return nil, nil
836868
}
837869
if sourceVal.Type().Kind() == reflect.Struct {
838-
for i := 0; i < sourceVal.NumField(); i++ {
839-
valueField := sourceVal.Field(i)
840-
typeField := sourceVal.Type().Field(i)
841-
// try matching the field name first
842-
if typeField.Name == p.Info.FieldName {
843-
return valueField.Interface(), nil
844-
}
845-
tag := typeField.Tag
846-
checkTag := func(tagName string) bool {
847-
t := tag.Get(tagName)
848-
tOptions := strings.Split(t, ",")
849-
if len(tOptions) == 0 {
850-
return false
851-
}
852-
if tOptions[0] != p.Info.FieldName {
853-
return false
854-
}
855-
return true
856-
}
857-
if checkTag("json") || checkTag("graphql") {
858-
return valueField.Interface(), nil
859-
} else {
860-
continue
861-
}
862-
}
863-
return nil, nil
870+
return defaultResolveStruct(sourceVal, p.Info.FieldName)
864871
}
865872

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

0 commit comments

Comments
 (0)