From d8d9996464f6a52ca46f5562163328cb04022ad4 Mon Sep 17 00:00:00 2001 From: John Guo Date: Fri, 11 Mar 2022 10:24:42 +0800 Subject: [PATCH] fix issue #1662 --- database/gdb/gdb_core.go | 3 +- database/gdb/gdb_core_transaction.go | 4 +- database/gdb/gdb_func.go | 7 +- database/gdb/gdb_model_insert.go | 10 +-- database/gdb/gdb_model_select.go | 4 +- database/gdb/gdb_model_update.go | 4 +- database/gredis/gredis_redis_conn.go | 4 +- encoding/gjson/gjson.go | 3 +- encoding/gjson/gjson_api_new_load.go | 4 +- internal/empty/empty.go | 6 +- .../reflection.go} | 15 ++-- internal/reflection/reflection_test.go | 69 +++++++++++++++++++ internal/utils/utils_z_unit_test.go | 55 --------------- net/ghttp/ghttp_server_router_group.go | 3 +- net/ghttp/ghttp_z_unit_issue_test.go | 58 ++++++++++++++++ os/gcmd/gcmd_command_object.go | 3 +- util/gconv/gconv.go | 4 +- util/gconv/gconv_slice_any.go | 4 +- util/gconv/gconv_slice_float.go | 6 +- util/gconv/gconv_slice_int.go | 8 +-- util/gconv/gconv_slice_str.go | 4 +- util/gconv/gconv_slice_uint.go | 7 +- util/gutil/gutil_dump.go | 4 +- util/gvalid/gvalid_validator.go | 3 +- util/gvalid/gvalid_validator_check_map.go | 4 +- util/gvalid/gvalid_validator_check_struct.go | 11 +-- util/gvalid/gvalid_validator_check_value.go | 6 +- 27 files changed, 200 insertions(+), 113 deletions(-) rename internal/{utils/utils_reflect.go => reflection/reflection.go} (87%) create mode 100644 internal/reflection/reflection_test.go diff --git a/database/gdb/gdb_core.go b/database/gdb/gdb_core.go index 255b67c77..0dd217829 100644 --- a/database/gdb/gdb_core.go +++ b/database/gdb/gdb_core.go @@ -18,6 +18,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/intlog" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" @@ -201,7 +202,7 @@ func (c *Core) GetStructs(ctx context.Context, pointer interface{}, sql string, // the conversion. If parameter `pointer` is type of slice, it calls GetStructs internally // for conversion. func (c *Core) GetScan(ctx context.Context, pointer interface{}, sql string, args ...interface{}) error { - reflectInfo := utils.OriginTypeAndKind(pointer) + reflectInfo := reflection.OriginTypeAndKind(pointer) if reflectInfo.InputKind != reflect.Ptr { return gerror.NewCodef( gcode.CodeInvalidParameter, diff --git a/database/gdb/gdb_core_transaction.go b/database/gdb/gdb_core_transaction.go index 7dcad3873..dc57d38f6 100644 --- a/database/gdb/gdb_core_transaction.go +++ b/database/gdb/gdb_core_transaction.go @@ -14,7 +14,7 @@ import ( "github.com/gogf/gf/v2/container/gtype" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/util/gconv" ) @@ -341,7 +341,7 @@ func (tx *TX) GetStructs(objPointerSlice interface{}, sql string, args ...interf // the conversion. If parameter `pointer` is type of slice, it calls GetStructs internally // for conversion. func (tx *TX) GetScan(pointer interface{}, sql string, args ...interface{}) error { - reflectInfo := utils.OriginTypeAndKind(pointer) + reflectInfo := reflection.OriginTypeAndKind(pointer) if reflectInfo.InputKind != reflect.Ptr { return gerror.NewCodef( gcode.CodeInvalidParameter, diff --git a/database/gdb/gdb_func.go b/database/gdb/gdb_func.go index 4c20d26a7..04cdd17f6 100644 --- a/database/gdb/gdb_func.go +++ b/database/gdb/gdb_func.go @@ -15,6 +15,7 @@ import ( "time" "github.com/gogf/gf/v2/internal/empty" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/os/gstructs" "github.com/gogf/gf/v2/os/gtime" @@ -366,7 +367,7 @@ func isKeyValueCanBeOmitEmpty(omitEmpty bool, whereType string, key, value inter func formatWhereHolder(db DB, in formatWhereHolderInput) (newWhere string, newArgs []interface{}) { var ( buffer = bytes.NewBuffer(nil) - reflectInfo = utils.OriginValueAndKind(in.Where) + reflectInfo = reflection.OriginValueAndKind(in.Where) ) switch reflectInfo.OriginKind { case reflect.Array, reflect.Slice: @@ -707,7 +708,7 @@ func handleArguments(sql string, args []interface{}) (newSql string, newArgs []i // Handles the slice arguments. if len(args) > 0 { for index, arg := range args { - reflectInfo := utils.OriginValueAndKind(arg) + reflectInfo := reflection.OriginValueAndKind(arg) switch reflectInfo.OriginKind { case reflect.Slice, reflect.Array: // It does not split the type of []byte. @@ -817,7 +818,7 @@ func FormatSqlWithArgs(sql string, args []interface{}) string { if v, ok := args[index].(Raw); ok { return gconv.String(v) } - reflectInfo := utils.OriginValueAndKind(args[index]) + reflectInfo := reflection.OriginValueAndKind(args[index]) if reflectInfo.OriginKind == reflect.Ptr && (reflectInfo.OriginValue.IsNil() || !reflectInfo.OriginValue.IsValid()) { return "null" diff --git a/database/gdb/gdb_model_insert.go b/database/gdb/gdb_model_insert.go index 09787ec93..7039bd38b 100644 --- a/database/gdb/gdb_model_insert.go +++ b/database/gdb/gdb_model_insert.go @@ -13,7 +13,7 @@ import ( "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" @@ -69,7 +69,7 @@ func (m *Model) Data(data ...interface{}) *Model { model.data = gutil.MapCopy(value) default: - reflectInfo := utils.OriginValueAndKind(value) + reflectInfo := reflection.OriginValueAndKind(value) switch reflectInfo.OriginKind { case reflect.Slice, reflect.Array: if reflectInfo.OriginValue.Len() > 0 { @@ -253,7 +253,7 @@ func (m *Model) doInsertWithOption(insertOption int) (result sql.Result, err err list = List{m.db.ConvertDataForRecord(m.GetCtx(), value)} default: - reflectInfo := utils.OriginValueAndKind(newData) + reflectInfo := reflection.OriginValueAndKind(newData) switch reflectInfo.OriginKind { // If it's slice type, it then converts it to List type. case reflect.Slice, reflect.Array: @@ -330,7 +330,7 @@ func (m *Model) formatDoInsertOption(insertOption int, columnNames []string) (op option.OnDuplicateStr = gconv.String(m.onDuplicate) default: - reflectInfo := utils.OriginValueAndKind(m.onDuplicate) + reflectInfo := reflection.OriginValueAndKind(m.onDuplicate) switch reflectInfo.OriginKind { case reflect.String: option.OnDuplicateMap = make(map[string]interface{}) @@ -385,7 +385,7 @@ func (m *Model) formatOnDuplicateExKeys(onDuplicateEx interface{}) ([]string, er return nil, nil } - reflectInfo := utils.OriginValueAndKind(onDuplicateEx) + reflectInfo := reflection.OriginValueAndKind(onDuplicateEx) switch reflectInfo.OriginKind { case reflect.String: return gstr.SplitAndTrim(reflectInfo.OriginValue.String(), ","), nil diff --git a/database/gdb/gdb_model_select.go b/database/gdb/gdb_model_select.go index 2fcc84b2d..2ea93e3a3 100644 --- a/database/gdb/gdb_model_select.go +++ b/database/gdb/gdb_model_select.go @@ -17,7 +17,7 @@ import ( "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/intlog" "github.com/gogf/gf/v2/internal/json" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" ) @@ -294,7 +294,7 @@ func (m *Model) doStructs(pointer interface{}, where ...interface{}) error { // users := ([]*User)(nil) // err := db.Model("user").Scan(&users). func (m *Model) Scan(pointer interface{}, where ...interface{}) error { - reflectInfo := utils.OriginTypeAndKind(pointer) + reflectInfo := reflection.OriginTypeAndKind(pointer) if reflectInfo.InputKind != reflect.Ptr { return gerror.NewCode( gcode.CodeInvalidParameter, diff --git a/database/gdb/gdb_model_update.go b/database/gdb/gdb_model_update.go index c6fe04c6f..064fccceb 100644 --- a/database/gdb/gdb_model_update.go +++ b/database/gdb/gdb_model_update.go @@ -13,7 +13,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" @@ -49,7 +49,7 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro ) // Automatically update the record updating time. if !m.unscoped && fieldNameUpdate != "" { - reflectInfo := utils.OriginTypeAndKind(m.data) + reflectInfo := reflection.OriginTypeAndKind(m.data) switch reflectInfo.OriginKind { case reflect.Map, reflect.Struct: dataMap := m.db.ConvertDataForRecord(m.GetCtx(), m.data) diff --git a/database/gredis/gredis_redis_conn.go b/database/gredis/gredis_redis_conn.go index 2bef863e3..720e738a3 100644 --- a/database/gredis/gredis_redis_conn.go +++ b/database/gredis/gredis_redis_conn.go @@ -13,7 +13,7 @@ import ( "github.com/gogf/gf/v2" "github.com/gogf/gf/v2/container/gvar" "github.com/gogf/gf/v2/internal/json" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/os/gtime" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" @@ -33,7 +33,7 @@ func (c *RedisConn) Do(ctx context.Context, command string, args ...interface{}) } for k, v := range args { var ( - reflectInfo = utils.OriginTypeAndKind(v) + reflectInfo = reflection.OriginTypeAndKind(v) ) switch reflectInfo.OriginKind { case diff --git a/encoding/gjson/gjson.go b/encoding/gjson/gjson.go index c7938ad3f..1a7e8efce 100644 --- a/encoding/gjson/gjson.go +++ b/encoding/gjson/gjson.go @@ -14,6 +14,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/rwmutex" "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/text/gstr" @@ -282,7 +283,7 @@ func (j *Json) convertValue(value interface{}) (convertedValue interface{}, err default: var ( - reflectInfo = utils.OriginValueAndKind(value) + reflectInfo = reflection.OriginValueAndKind(value) ) switch reflectInfo.OriginKind { case reflect.Array: diff --git a/encoding/gjson/gjson_api_new_load.go b/encoding/gjson/gjson_api_new_load.go index 75f8e7bef..412854b5c 100644 --- a/encoding/gjson/gjson_api_new_load.go +++ b/encoding/gjson/gjson_api_new_load.go @@ -17,8 +17,8 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/rwmutex" - "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/util/gconv" @@ -69,7 +69,7 @@ func NewWithOptions(data interface{}, options Options) *Json { default: var ( pointedData interface{} - reflectInfo = utils.OriginValueAndKind(data) + reflectInfo = reflection.OriginValueAndKind(data) ) switch reflectInfo.OriginKind { case reflect.Slice, reflect.Array: diff --git a/internal/empty/empty.go b/internal/empty/empty.go index 88b53c814..551457ce9 100644 --- a/internal/empty/empty.go +++ b/internal/empty/empty.go @@ -10,6 +10,8 @@ package empty import ( "reflect" "time" + + "github.com/gogf/gf/v2/internal/reflection" ) // iString is used for type assert api for String(). @@ -151,8 +153,10 @@ func IsEmpty(value interface{}) bool { return rv.Len() == 0 case reflect.Struct: + var fieldValueInterface interface{} for i := 0; i < rv.NumField(); i++ { - if !IsEmpty(rv.Field(i).Interface()) { + fieldValueInterface, _ = reflection.ValueToInterface(rv.Field(i)) + if !IsEmpty(fieldValueInterface) { return false } } diff --git a/internal/utils/utils_reflect.go b/internal/reflection/reflection.go similarity index 87% rename from internal/utils/utils_reflect.go rename to internal/reflection/reflection.go index 6897fa8dd..30a4cdedc 100644 --- a/internal/utils/utils_reflect.go +++ b/internal/reflection/reflection.go @@ -4,9 +4,12 @@ // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. -package utils +// Package reflection provides some reflection functions for internal usage. +package reflection -import "reflect" +import ( + "reflect" +) type OriginValueAndKindOutput struct { InputValue reflect.Value @@ -63,8 +66,8 @@ func OriginTypeAndKind(value interface{}) (out OriginTypeAndKindOutput) { return } -// ReflectValueToInterface converts reflect value to its interface type. -func ReflectValueToInterface(v reflect.Value) (value interface{}, ok bool) { +// ValueToInterface converts reflect value to its interface type. +func ValueToInterface(v reflect.Value) (value interface{}, ok bool) { if v.IsValid() && v.CanInterface() { return v.Interface(), true } @@ -82,9 +85,9 @@ func ReflectValueToInterface(v reflect.Value) (value interface{}, ok bool) { case reflect.String: return v.String(), true case reflect.Ptr: - return ReflectValueToInterface(v.Elem()) + return ValueToInterface(v.Elem()) case reflect.Interface: - return ReflectValueToInterface(v.Elem()) + return ValueToInterface(v.Elem()) default: return nil, false } diff --git a/internal/reflection/reflection_test.go b/internal/reflection/reflection_test.go new file mode 100644 index 000000000..417cf807c --- /dev/null +++ b/internal/reflection/reflection_test.go @@ -0,0 +1,69 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package reflection_test + +import ( + "reflect" + "testing" + + "github.com/gogf/gf/v2/internal/reflection" + "github.com/gogf/gf/v2/test/gtest" +) + +func Test_OriginValueAndKind(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var s = "s" + out := reflection.OriginValueAndKind(s) + t.Assert(out.InputKind, reflect.String) + t.Assert(out.OriginKind, reflect.String) + }) + gtest.C(t, func(t *gtest.T) { + var s = "s" + out := reflection.OriginValueAndKind(&s) + t.Assert(out.InputKind, reflect.Ptr) + t.Assert(out.OriginKind, reflect.String) + }) + gtest.C(t, func(t *gtest.T) { + var s []int + out := reflection.OriginValueAndKind(s) + t.Assert(out.InputKind, reflect.Slice) + t.Assert(out.OriginKind, reflect.Slice) + }) + gtest.C(t, func(t *gtest.T) { + var s []int + out := reflection.OriginValueAndKind(&s) + t.Assert(out.InputKind, reflect.Ptr) + t.Assert(out.OriginKind, reflect.Slice) + }) +} + +func Test_OriginTypeAndKind(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var s = "s" + out := reflection.OriginTypeAndKind(s) + t.Assert(out.InputKind, reflect.String) + t.Assert(out.OriginKind, reflect.String) + }) + gtest.C(t, func(t *gtest.T) { + var s = "s" + out := reflection.OriginTypeAndKind(&s) + t.Assert(out.InputKind, reflect.Ptr) + t.Assert(out.OriginKind, reflect.String) + }) + gtest.C(t, func(t *gtest.T) { + var s []int + out := reflection.OriginTypeAndKind(s) + t.Assert(out.InputKind, reflect.Slice) + t.Assert(out.OriginKind, reflect.Slice) + }) + gtest.C(t, func(t *gtest.T) { + var s []int + out := reflection.OriginTypeAndKind(&s) + t.Assert(out.InputKind, reflect.Ptr) + t.Assert(out.OriginKind, reflect.Slice) + }) +} diff --git a/internal/utils/utils_z_unit_test.go b/internal/utils/utils_z_unit_test.go index 91d8c8de0..2b3399008 100644 --- a/internal/utils/utils_z_unit_test.go +++ b/internal/utils/utils_z_unit_test.go @@ -8,7 +8,6 @@ package utils_test import ( "io/ioutil" - "reflect" "testing" "github.com/gogf/gf/v2/internal/utils" @@ -72,57 +71,3 @@ func Test_RemoveSymbols(t *testing.T) { t.Assert(utils.RemoveSymbols(`-a-b我._a c1!@#$%^&*是()_+:帅";'.,哥'01`), `ab我ac1是帅哥01`) }) } - -func Test_OriginValueAndKind(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var s = "s" - out := utils.OriginValueAndKind(s) - t.Assert(out.InputKind, reflect.String) - t.Assert(out.OriginKind, reflect.String) - }) - gtest.C(t, func(t *gtest.T) { - var s = "s" - out := utils.OriginValueAndKind(&s) - t.Assert(out.InputKind, reflect.Ptr) - t.Assert(out.OriginKind, reflect.String) - }) - gtest.C(t, func(t *gtest.T) { - var s []int - out := utils.OriginValueAndKind(s) - t.Assert(out.InputKind, reflect.Slice) - t.Assert(out.OriginKind, reflect.Slice) - }) - gtest.C(t, func(t *gtest.T) { - var s []int - out := utils.OriginValueAndKind(&s) - t.Assert(out.InputKind, reflect.Ptr) - t.Assert(out.OriginKind, reflect.Slice) - }) -} - -func Test_OriginTypeAndKind(t *testing.T) { - gtest.C(t, func(t *gtest.T) { - var s = "s" - out := utils.OriginTypeAndKind(s) - t.Assert(out.InputKind, reflect.String) - t.Assert(out.OriginKind, reflect.String) - }) - gtest.C(t, func(t *gtest.T) { - var s = "s" - out := utils.OriginTypeAndKind(&s) - t.Assert(out.InputKind, reflect.Ptr) - t.Assert(out.OriginKind, reflect.String) - }) - gtest.C(t, func(t *gtest.T) { - var s []int - out := utils.OriginTypeAndKind(s) - t.Assert(out.InputKind, reflect.Slice) - t.Assert(out.OriginKind, reflect.Slice) - }) - gtest.C(t, func(t *gtest.T) { - var s []int - out := utils.OriginTypeAndKind(&s) - t.Assert(out.InputKind, reflect.Ptr) - t.Assert(out.OriginKind, reflect.Slice) - }) -} diff --git a/net/ghttp/ghttp_server_router_group.go b/net/ghttp/ghttp_server_router_group.go index 75535c02b..a4a6cc9fb 100644 --- a/net/ghttp/ghttp_server_router_group.go +++ b/net/ghttp/ghttp_server_router_group.go @@ -12,6 +12,7 @@ import ( "reflect" "github.com/gogf/gf/v2/debug/gdebug" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" @@ -158,7 +159,7 @@ func (g *RouterGroup) Bind(handlerOrObject ...interface{}) *RouterGroup { for _, v := range handlerOrObject { var ( item = v - originValueAndKind = utils.OriginValueAndKind(item) + originValueAndKind = reflection.OriginValueAndKind(item) ) switch originValueAndKind.OriginKind { diff --git a/net/ghttp/ghttp_z_unit_issue_test.go b/net/ghttp/ghttp_z_unit_issue_test.go index 4e1bef297..f8e3b437e 100644 --- a/net/ghttp/ghttp_z_unit_issue_test.go +++ b/net/ghttp/ghttp_z_unit_issue_test.go @@ -166,3 +166,61 @@ func Test_Issue1653(t *testing.T) { t.Assert(resContent, `{"code":0,"message":"","data":{"uuid":"28ee701c-7daf-4cdc-9a62-6d6704e6112b","feed_back":"P00001"}}`) }) } + +type LbseMasterHead struct { + Code string `json:"code" v:"code@required|min-length:1#The code is required"` + Active bool `json:"active"` + Preset bool `json:"preset"` + Superior string `json:"superior"` + Path []string `json:"path"` + Sort int `json:"sort"` + Folder bool `json:"folder"` + Test string `json:"test" v:"required"` +} + +type Template struct { + LbseMasterHead + Datasource string `json:"datasource" v:"required|length:32,32#The datasource is required"` + SQLText string `json:"sql_text"` +} + +type TemplateCreateReq struct { + g.Meta `path:"/test" method:"post" summary:"Create template" tags:"Template"` + Master Template `json:"master"` +} + +type TemplateCreateRes struct{} + +type cFoo1 struct{} + +var Foo1 = new(cFoo1) + +func (r cFoo1) PostTest1(ctx context.Context, req *TemplateCreateReq) (res *TemplateCreateRes, err error) { + g.Dump(req) + return +} + +// https://github.com/gogf/gf/issues/1662 +func Test_Issue662(t *testing.T) { + s := g.Server(guid.S()) + s.Use(ghttp.MiddlewareHandlerResponse) + s.Group("/boot", func(grp *ghttp.RouterGroup) { + grp.Bind(Foo1) + }) + s.SetPort(8888) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + time.Sleep(1000 * time.Millisecond) + + // g.Client()测试: + // code字段传入空字符串时,校验没有提示 + gtest.C(t, func(t *gtest.T) { + c := g.Client() + c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + dataReq := ` +{"master":{"active":true,"code":"","created_at":"","created_by":"","created_by_text":"","datasource":"38b6f170-a584-43fc-8912-cc1e9bf1b1a9","description":"币种","folder":false,"path":"[\"XCUR\"]","preset":false,"sort":1000,"sql_text":"SELECT!!!!","superior":null,"updated_at":"","updated_by":"","updated_by_text":"","updated_tick":0,"uuid":""},"translation":[{"code":"zh_CN","text":"币种"},{"code":"en_US","text":"币种"}],"filters":null,"fields":[{"code":"F001","created_at":"2022-01-18 23:37:38","created_by":"3ed72aba-1622-4262-a61e-83581e020763","field":"value","hide":false,"min_width":120,"name":"value","parent":"296154bf-b718-4e8f-8b70-efb969b831ec","updated_at":"2022-01-18 23:37:38","updated_by":"3ed72aba-1622-4262-a61e-83581e020763","updated_tick":1,"uuid":"f2140b7a-044c-41c3-b70e-852e6160b21b"},{"code":"F002","created_at":"2022-01-18 23:37:38","created_by":"3ed72aba-1622-4262-a61e-83581e020763","field":"label","hide":false,"min_width":120,"name":"label","parent":"296154bf-b718-4e8f-8b70-efb969b831ec","updated_at":"2022-01-18 23:37:38","updated_by":"3ed72aba-1622-4262-a61e-83581e020763","updated_tick":1,"uuid":"2d3bba5d-308b-4dba-bcac-f093e6556eca"}],"limit":0} +` + t.Assert(c.PostContent(ctx, "/boot/test", dataReq), `{"code":51,"message":"The code is required","data":null}`) + }) +} diff --git a/os/gcmd/gcmd_command_object.go b/os/gcmd/gcmd_command_object.go index faf9ce706..ddf37151d 100644 --- a/os/gcmd/gcmd_command_object.go +++ b/os/gcmd/gcmd_command_object.go @@ -14,6 +14,7 @@ import ( "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/os/gstructs" "github.com/gogf/gf/v2/text/gstr" @@ -38,7 +39,7 @@ var ( // NewFromObject creates and returns a root command object using given object. func NewFromObject(object interface{}) (rootCmd *Command, err error) { - originValueAndKind := utils.OriginValueAndKind(object) + originValueAndKind := reflection.OriginValueAndKind(object) if originValueAndKind.OriginKind != reflect.Struct { err = gerror.Newf( `input object should be type of struct, but got "%s"`, diff --git a/util/gconv/gconv.go b/util/gconv/gconv.go index 8ca25c547..48fd0490f 100644 --- a/util/gconv/gconv.go +++ b/util/gconv/gconv.go @@ -21,7 +21,7 @@ import ( "github.com/gogf/gf/v2/encoding/gbinary" "github.com/gogf/gf/v2/internal/intlog" "github.com/gogf/gf/v2/internal/json" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/os/gtime" ) @@ -317,7 +317,7 @@ func Bytes(any interface{}) []byte { if f, ok := value.(iBytes); ok { return f.Bytes() } - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Map: bytes, err := json.Marshal(any) diff --git a/util/gconv/gconv_slice_any.go b/util/gconv/gconv_slice_any.go index 092d19694..9041886d3 100644 --- a/util/gconv/gconv_slice_any.go +++ b/util/gconv/gconv_slice_any.go @@ -9,7 +9,7 @@ package gconv import ( "reflect" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" ) // SliceAny is alias of Interfaces. @@ -107,7 +107,7 @@ func Interfaces(any interface{}) []interface{} { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( diff --git a/util/gconv/gconv_slice_float.go b/util/gconv/gconv_slice_float.go index 56c774e33..4816d7044 100644 --- a/util/gconv/gconv_slice_float.go +++ b/util/gconv/gconv_slice_float.go @@ -9,7 +9,7 @@ package gconv import ( "reflect" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" ) // SliceFloat is alias of Floats. @@ -132,7 +132,7 @@ func Float32s(any interface{}) []float32 { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( @@ -252,7 +252,7 @@ func Float64s(any interface{}) []float64 { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( diff --git a/util/gconv/gconv_slice_int.go b/util/gconv/gconv_slice_int.go index c34701bb9..1ca0ab4d6 100644 --- a/util/gconv/gconv_slice_int.go +++ b/util/gconv/gconv_slice_int.go @@ -9,7 +9,7 @@ package gconv import ( "reflect" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" ) // SliceInt is alias of Ints. @@ -132,7 +132,7 @@ func Ints(any interface{}) []int { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( @@ -257,7 +257,7 @@ func Int32s(any interface{}) []int32 { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( @@ -382,7 +382,7 @@ func Int64s(any interface{}) []int64 { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( diff --git a/util/gconv/gconv_slice_str.go b/util/gconv/gconv_slice_str.go index 9118bd522..31e766f52 100644 --- a/util/gconv/gconv_slice_str.go +++ b/util/gconv/gconv_slice_str.go @@ -9,7 +9,7 @@ package gconv import ( "reflect" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" ) // SliceStr is alias of Strings. @@ -118,7 +118,7 @@ func Strings(any interface{}) []string { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( diff --git a/util/gconv/gconv_slice_uint.go b/util/gconv/gconv_slice_uint.go index 01d7a1d97..e77dfc2c0 100644 --- a/util/gconv/gconv_slice_uint.go +++ b/util/gconv/gconv_slice_uint.go @@ -10,6 +10,7 @@ import ( "reflect" "strings" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/utils" ) @@ -141,7 +142,7 @@ func Uints(any interface{}) []uint { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( @@ -271,7 +272,7 @@ func Uint32s(any interface{}) []uint32 { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( @@ -401,7 +402,7 @@ func Uint64s(any interface{}) []uint64 { return array } // Not a common type, it then uses reflection for conversion. - originValueAndKind := utils.OriginValueAndKind(any) + originValueAndKind := reflection.OriginValueAndKind(any) switch originValueAndKind.OriginKind { case reflect.Slice, reflect.Array: var ( diff --git a/util/gutil/gutil_dump.go b/util/gutil/gutil_dump.go index 53c8aeda5..32cc09589 100644 --- a/util/gutil/gutil_dump.go +++ b/util/gutil/gutil_dump.go @@ -13,7 +13,7 @@ import ( "reflect" "strings" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/os/gstructs" "github.com/gogf/gf/v2/text/gstr" ) @@ -90,7 +90,7 @@ func doDump(value interface{}, indent string, buffer *bytes.Buffer, option doDum if v.CanInterface() { value = v.Interface() } else { - if convertedValue, ok := utils.ReflectValueToInterface(v); ok { + if convertedValue, ok := reflection.ValueToInterface(v); ok { value = convertedValue } } diff --git a/util/gvalid/gvalid_validator.go b/util/gvalid/gvalid_validator.go index 80ac39d9a..a625d6f66 100644 --- a/util/gvalid/gvalid_validator.go +++ b/util/gvalid/gvalid_validator.go @@ -12,6 +12,7 @@ import ( "reflect" "github.com/gogf/gf/v2/i18n/gi18n" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/util/gconv" ) @@ -46,7 +47,7 @@ func (v *Validator) Run(ctx context.Context) Error { ) } - originValueAndKind := utils.OriginValueAndKind(v.data) + originValueAndKind := reflection.OriginValueAndKind(v.data) switch originValueAndKind.OriginKind { case reflect.Map: isMapValidation := false diff --git a/util/gvalid/gvalid_validator_check_map.go b/util/gvalid/gvalid_validator_check_map.go index db67a8d59..997706751 100644 --- a/util/gvalid/gvalid_validator_check_map.go +++ b/util/gvalid/gvalid_validator_check_map.go @@ -13,7 +13,7 @@ import ( "strings" "github.com/gogf/gf/v2/errors/gcode" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/util/gconv" ) @@ -97,7 +97,7 @@ func (v *Validator) doCheckMap(ctx context.Context, params interface{}) Error { validator.rules = nil validator.messages = nil for _, item := range inputParamMap { - originTypeAndKind := utils.OriginTypeAndKind(item) + originTypeAndKind := reflection.OriginTypeAndKind(item) switch originTypeAndKind.OriginKind { case reflect.Map, reflect.Struct, reflect.Slice, reflect.Array: v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{ diff --git a/util/gvalid/gvalid_validator_check_struct.go b/util/gvalid/gvalid_validator_check_struct.go index 3e4f8dcdc..e4cee548d 100644 --- a/util/gvalid/gvalid_validator_check_struct.go +++ b/util/gvalid/gvalid_validator_check_struct.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/internal/empty" "github.com/gogf/gf/v2/os/gstructs" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gmeta" @@ -23,6 +24,8 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error errorMaps = make(map[string]map[string]error) // Returning error. fieldToAliasNameMap = make(map[string]string) // Field names to alias name map. resultSequenceRules = make([]fieldRule, 0) + isEmptyData = empty.IsEmpty(v.data) + isEmptyAssoc = empty.IsEmpty(v.assoc) ) fieldMap, err := gstructs.FieldMap(gstructs.FieldMapInput{ Pointer: object, @@ -39,7 +42,7 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error return newValidationErrorByStr(internalObjectErrRuleName, err) } // If there's no struct tag and validation rules, it does nothing and returns quickly. - if len(tagFields) == 0 && v.messages == nil { + if len(tagFields) == 0 && v.messages == nil && isEmptyData && isEmptyAssoc { return nil } @@ -102,7 +105,7 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error } } // If there's no struct tag and validation rules, it does nothing and returns quickly. - if len(tagFields) == 0 && len(checkRules) == 0 { + if len(tagFields) == 0 && len(checkRules) == 0 && isEmptyData && isEmptyAssoc { return nil } // Input parameter map handling. @@ -221,9 +224,7 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error } // Temporary variable for value. - var ( - value interface{} - ) + var value interface{} // It checks the struct recursively if its attribute is an embedded struct. for _, field := range fieldMap { diff --git a/util/gvalid/gvalid_validator_check_value.go b/util/gvalid/gvalid_validator_check_value.go index 2a3838baa..ae6808791 100644 --- a/util/gvalid/gvalid_validator_check_value.go +++ b/util/gvalid/gvalid_validator_check_value.go @@ -18,7 +18,7 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/json" - "github.com/gogf/gf/v2/internal/utils" + "github.com/gogf/gf/v2/internal/reflection" "github.com/gogf/gf/v2/net/gipv4" "github.com/gogf/gf/v2/net/gipv6" "github.com/gogf/gf/v2/os/gtime" @@ -565,7 +565,7 @@ func (v *Validator) doCheckValueRecursively(ctx context.Context, in doCheckValue case reflect.Map: var dataMap = gconv.Map(in.Value) for _, item := range dataMap { - originTypeAndKind := utils.OriginTypeAndKind(item) + originTypeAndKind := reflection.OriginTypeAndKind(item) v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{ Value: item, Type: originTypeAndKind.InputType, @@ -585,7 +585,7 @@ func (v *Validator) doCheckValueRecursively(ctx context.Context, in doCheckValue return } for _, item := range array { - originTypeAndKind := utils.OriginTypeAndKind(item) + originTypeAndKind := reflection.OriginTypeAndKind(item) v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{ Value: item, Type: originTypeAndKind.InputType,