Skip to content

Commit 732b137

Browse files
committed
improve convert map performance
1 parent 6b3c61f commit 732b137

File tree

1 file changed

+56
-8
lines changed

1 file changed

+56
-8
lines changed

language/visitor/visitor.go

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package visitor
22

33
import (
4-
"encoding/json"
5-
"reflect"
6-
4+
"fmt"
75
"github.com/graphql-go/graphql/language/ast"
86
"github.com/graphql-go/graphql/language/typeInfo"
7+
"reflect"
98
)
109

1110
const (
@@ -446,14 +445,63 @@ func convertMap(src interface{}) (dest map[string]interface{}, err error) {
446445
if src == nil {
447446
return
448447
}
449-
var bts []byte
450-
if bts, err = json.Marshal(src); err != nil {
448+
449+
// return if src is already a map
450+
dest, ok := src.(map[string]interface{})
451+
if ok {
451452
return
452453
}
453-
if err = json.Unmarshal(bts, &dest); err != nil {
454-
return
454+
455+
outputMap := make(map[string]interface{})
456+
val := reflect.ValueOf(src)
457+
458+
// Dereference pointer if necessary
459+
if val.Kind() == reflect.Ptr {
460+
if val.IsNil() {
461+
return nil, fmt.Errorf("input is a nil pointer")
462+
}
463+
val = val.Elem()
464+
}
465+
466+
if val.Kind() != reflect.Struct {
467+
return nil, fmt.Errorf("input is not a struct or pointer to struct")
455468
}
456-
return
469+
470+
typ := val.Type()
471+
for i := 0; i < val.NumField(); i++ {
472+
field := val.Field(i)
473+
fieldName := typ.Field(i).Name
474+
475+
switch field.Kind() {
476+
case reflect.Ptr:
477+
if field.IsNil() {
478+
outputMap[fieldName] = nil
479+
} else {
480+
nestedMap, err := convertMap(field.Interface())
481+
if err != nil {
482+
return nil, err
483+
}
484+
outputMap[fieldName] = nestedMap
485+
}
486+
case reflect.Struct:
487+
nestedMap, err := convertMap(field.Interface())
488+
if err != nil {
489+
return nil, err
490+
}
491+
outputMap[fieldName] = nestedMap
492+
case reflect.Interface:
493+
if field.IsNil() {
494+
outputMap[fieldName] = nil
495+
} else {
496+
concreteValue := field.Elem()
497+
outputMap[fieldName], _ = convertMap(concreteValue.Interface())
498+
}
499+
default:
500+
outputMap[fieldName] = field.Interface()
501+
}
502+
}
503+
504+
return outputMap, nil
457505
}
458506

459507
// get value by key from struct | slice | map | wrap(prev)

0 commit comments

Comments
 (0)