diff --git a/g/database/gdb/gdb_func.go b/g/database/gdb/gdb_func.go index 63a11f846..e7e8b8181 100644 --- a/g/database/gdb/gdb_func.go +++ b/g/database/gdb/gdb_func.go @@ -20,6 +20,11 @@ import ( "time" ) +// Type assert api for String(). +type apiString interface { + String() string +} + // 格式化SQL查询条件 func formatCondition(where interface{}, args []interface{}) (newWhere string, newArgs []interface{}) { // 条件字符串处理 @@ -187,3 +192,32 @@ func getInsertOperationByOption(option int) string { } return operator } + +// 将对象转换为map,如果对象带有继承对象,那么执行递归转换。 +// 该方法用于将变量传递给数据库执行之前。 +func structToMap(obj interface{}) map[string]interface{} { + data := gconv.Map(obj) + for k, v := range data { + rv := reflect.ValueOf(v) + kind := rv.Kind() + if kind == reflect.Ptr { + rv = rv.Elem() + kind = rv.Kind() + } + switch kind { + case reflect.Struct: + // 底层数据库引擎支持 time.Time 类型 + if _, ok := v.(time.Time); ok { + continue + } + // 如果执行String方法,那么执行字符串转换 + if s, ok := v.(apiString); ok { + data[k] = s.String() + } + for k, v := range structToMap(v) { + data[k] = v + } + } + } + return data +} \ No newline at end of file diff --git a/g/util/gconv/gconv_map.go b/g/util/gconv/gconv_map.go index 94f6f72e9..6da49ee48 100644 --- a/g/util/gconv/gconv_map.go +++ b/g/util/gconv/gconv_map.go @@ -13,6 +13,9 @@ import ( "strings" ) +const ( + gGCONV_TAG = "gconv" +) // Map converts any variable to map[string]interface{}. // If the parameter is not a map type, then the conversion will fail and returns nil. // If is a struct object, the second parameter specifies the most priority @@ -102,8 +105,7 @@ func Map(value interface{}, tags...string) map[string]interface{} { case reflect.Struct: rt := rv.Type() name := "" - gconvTag := "gconv" - tagArray := []string{gconvTag, "json"} + tagArray := []string{gGCONV_TAG, "json"} switch len(tags) { case 0: // No need handle. @@ -112,8 +114,8 @@ func Map(value interface{}, tags...string) map[string]interface{} { default: tagArray = tags } - if gstr.SearchArray(tagArray, gconvTag) < 0 { - tagArray = append(tagArray, gconvTag) + if gstr.SearchArray(tagArray, gGCONV_TAG) < 0 { + tagArray = append(tagArray, gGCONV_TAG) } for i := 0; i < rv.NumField(); i++ { // Only convert the public attributes.