Skip to content

Commit c13c47a

Browse files
authored
Merge pull request graphql-go#440 from atombender/issue-439
Support custom map types in resolvers
2 parents bf68c1b + 66aaed7 commit c13c47a

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

executor.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,22 @@ func DefaultResolveFn(p ResolveParams) (interface{}, error) {
964964
return property, nil
965965
}
966966

967+
// Try accessing as map via reflection
968+
if r := reflect.ValueOf(p.Source); r.Kind() == reflect.Map && r.Type().Key().Kind() == reflect.String {
969+
val := r.MapIndex(reflect.ValueOf(p.Info.FieldName))
970+
if val.IsValid() {
971+
property := val.Interface()
972+
if val.Type().Kind() == reflect.Func {
973+
// try type casting the func to the most basic func signature
974+
// for more complex signatures, user have to define ResolveFn
975+
if propertyFn, ok := property.(func() interface{}); ok {
976+
return propertyFn(), nil
977+
}
978+
}
979+
return property, nil
980+
}
981+
}
982+
967983
// last resort, return nil
968984
return nil, nil
969985
}

executor_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,62 @@ func TestMergesParallelFragments(t *testing.T) {
297297
}
298298
}
299299

300+
type CustomMap map[string]interface{}
301+
302+
func TestCustomMapType(t *testing.T) {
303+
query := `
304+
query Example { data { a } }
305+
`
306+
data := CustomMap{
307+
"a": "1",
308+
"b": "2",
309+
}
310+
schema, err := graphql.NewSchema(graphql.SchemaConfig{
311+
Query: graphql.NewObject(graphql.ObjectConfig{
312+
Name: "RootQuery",
313+
Fields: graphql.Fields{
314+
"data": &graphql.Field{
315+
Type: graphql.NewObject(graphql.ObjectConfig{
316+
Name: "Data",
317+
Fields: graphql.Fields{
318+
"a": &graphql.Field{
319+
Type: graphql.String,
320+
},
321+
"b": &graphql.Field{
322+
Type: graphql.String,
323+
},
324+
},
325+
}),
326+
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
327+
return data, nil
328+
},
329+
},
330+
},
331+
}),
332+
})
333+
if err != nil {
334+
t.Fatalf("Error in schema %v", err.Error())
335+
}
336+
337+
result := testutil.TestExecute(t, graphql.ExecuteParams{
338+
Schema: schema,
339+
Root: data,
340+
AST: testutil.TestParse(t, query),
341+
})
342+
if len(result.Errors) > 0 {
343+
t.Fatalf("wrong result, unexpected errors: %v", result.Errors)
344+
}
345+
346+
expected := map[string]interface{}{
347+
"data": map[string]interface{}{
348+
"a": "1",
349+
},
350+
}
351+
if !reflect.DeepEqual(result.Data, expected) {
352+
t.Fatalf("Expected context.key to equal %v, got %v", expected, result.Data)
353+
}
354+
}
355+
300356
func TestThreadsSourceCorrectly(t *testing.T) {
301357

302358
query := `

0 commit comments

Comments
 (0)