1 Star 0 Fork 0

麦冬果果 / graphql-go

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
util.go 3.47 KB
一键复制 编辑 原始数据 按行查看 历史
Ahmad Muzakki 提交于 2017-12-18 16:35 . fix graphtype checking
package graphql
import (
"fmt"
"reflect"
"strings"
)
const TAG = "json"
// can't take recursive slice type
// e.g
// type Person struct{
// Friends []Person
// }
// it will throw panic stack-overflow
func BindFields(obj interface{}) Fields {
v := reflect.ValueOf(obj)
fields := make(map[string]*Field)
for i := 0; i < v.NumField(); i++ {
typeField := v.Type().Field(i)
tag := extractTag(typeField.Tag)
if tag == "-" {
continue
}
var graphType Output
if typeField.Type.Kind() == reflect.Struct {
structFields := BindFields(v.Field(i).Interface())
if tag == "" {
fields = appendFields(fields, structFields)
continue
} else {
graphType = NewObject(ObjectConfig{
Name: tag,
Fields: structFields,
})
}
}
if tag == "" {
continue
}
if graphType == nil {
graphType = getGraphType(typeField.Type)
}
fields[tag] = &Field{
Type: graphType,
Resolve: func(p ResolveParams) (interface{}, error) {
return extractValue(tag, p.Source), nil
},
}
}
return fields
}
func getGraphType(tipe reflect.Type) Output {
kind := tipe.Kind()
switch kind {
case reflect.String:
return String
case reflect.Int:
fallthrough
case reflect.Int8:
fallthrough
case reflect.Int32:
fallthrough
case reflect.Int64:
return Int
case reflect.Float32:
fallthrough
case reflect.Float64:
return Float
case reflect.Bool:
return Boolean
case reflect.Slice:
return getGraphList(tipe)
}
return String
}
func getGraphList(tipe reflect.Type) *List {
if tipe.Kind() == reflect.Slice {
switch tipe.Elem().Kind() {
case reflect.Int:
fallthrough
case reflect.Int8:
fallthrough
case reflect.Int32:
fallthrough
case reflect.Int64:
return NewList(Int)
case reflect.Bool:
return NewList(Boolean)
case reflect.Float32:
fallthrough
case reflect.Float64:
return NewList(Float)
case reflect.String:
return NewList(String)
}
}
// finaly bind object
t := reflect.New(tipe.Elem())
name := strings.Replace(fmt.Sprint(tipe.Elem()), ".", "_", -1)
obj := NewObject(ObjectConfig{
Name: name,
Fields: BindFields(t.Elem().Interface()),
})
return NewList(obj)
}
func appendFields(dest, origin Fields) Fields {
for key, value := range origin {
dest[key] = value
}
return dest
}
func extractValue(originTag string, obj interface{}) interface{} {
val := reflect.ValueOf(obj)
for j := 0; j < val.NumField(); j++ {
typeField := val.Type().Field(j)
if typeField.Type.Kind() == reflect.Struct {
res := extractValue(originTag, val.Field(j).Interface())
if res != nil {
return res
}
}
if originTag == extractTag(typeField.Tag) {
return val.Field(j).Interface()
}
}
return nil
}
func extractTag(tag reflect.StructTag) string {
t := tag.Get(TAG)
if t != "" {
t = strings.Split(t, ",")[0]
}
return t
}
// lazy way of binding args
func BindArg(obj interface{}, tags ...string) FieldConfigArgument {
v := reflect.ValueOf(obj)
var config = make(FieldConfigArgument)
for i := 0; i < v.NumField(); i++ {
typeField := v.Type().Field(i)
mytag := extractTag(typeField.Tag)
if inArray(tags, mytag) {
config[mytag] = &ArgumentConfig{
Type: getGraphType(typeField.Type),
}
}
}
return config
}
func inArray(slice interface{}, item interface{}) bool {
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
panic("inArray() given a non-slice type")
}
for i := 0; i < s.Len(); i++ {
if reflect.DeepEqual(item, s.Index(i).Interface()) {
return true
}
}
return false
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mdgg0816/graphql-go.git
git@gitee.com:mdgg0816/graphql-go.git
mdgg0816
graphql-go
graphql-go
v0.7.4

搜索帮助

344bd9b3 5694891 D2dac590 5694891