diff --git a/util/gvalid/gvalid_validator_check_struct.go b/util/gvalid/gvalid_validator_check_struct.go index 25738430aa3..e2ba2121e8b 100644 --- a/util/gvalid/gvalid_validator_check_struct.go +++ b/util/gvalid/gvalid_validator_check_struct.go @@ -296,12 +296,14 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error if value != nil { switch checkRuleItem.FieldKind { case reflect.Struct, reflect.Map: + // empty struct or map. if gconv.String(value) == emptyJsonObjectStr { - value = "" + value = nil } case reflect.Slice, reflect.Array: + // empty slice. if gconv.String(value) == emptyJsonArrayStr { - value = "" + value = []any{} } default: } diff --git a/util/gvalid/gvalid_z_unit_issue_test.go b/util/gvalid/gvalid_z_unit_issue_test.go index d7520d99d53..38aea073937 100644 --- a/util/gvalid/gvalid_z_unit_issue_test.go +++ b/util/gvalid/gvalid_z_unit_issue_test.go @@ -8,8 +8,15 @@ package gvalid_test import ( "context" + "fmt" "testing" + "time" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/guid" "github.com/gogf/gf/v2/util/gvalid" ) @@ -34,3 +41,76 @@ func Test_Issue2503(t *testing.T) { t.Fatal(err) } } + +type Issue3636SliceV struct{} + +func init() { + rule := Issue3636SliceV{} + gvalid.RegisterRule(rule.Name(), rule.Run) +} + +func (r Issue3636SliceV) Name() string { + return "slice-v" +} + +func (r Issue3636SliceV) Message() string { + return "not a slice" +} + +func (r Issue3636SliceV) Run(_ context.Context, in gvalid.RuleFuncInput) error { + for _, v := range in.Value.Slice() { + if v == "" { + return gerror.New("empty value") + } + } + if !in.Value.IsSlice() { + return gerror.New("not a slice") + } + return nil +} + +type Issue3636HelloReq struct { + g.Meta `path:"/hello" method:"POST"` + + Name string `json:"name" v:"required" dc:"Your name"` + S []string `json:"s" v:"slice-v" dc:"S"` +} +type Issue3636HelloRes struct { + Name string `json:"name" v:"required" dc:"Your name"` + S []string `json:"s" v:"slice-v" dc:"S"` +} + +type Issue3636Hello struct{} + +func (Issue3636Hello) Say(ctx context.Context, req *Issue3636HelloReq) (res *Issue3636HelloRes, err error) { + res = &Issue3636HelloRes{ + Name: req.Name, + S: req.S, + } + return +} + +// https://github.com/gogf/gf/issues/3636 +func Test_Issue3636(t *testing.T) { + s := g.Server(guid.S()) + s.Use(ghttp.MiddlewareHandlerResponse) + s.Group("/", func(group *ghttp.RouterGroup) { + group.Bind( + new(Issue3636Hello), + ) + }) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + + gtest.C(t, func(t *gtest.T) { + c := g.Client() + c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort())) + t.Assert( + c.PostContent(ctx, "/hello", `{"name": "t", "s" : []}`), + `{"code":0,"message":"","data":{"name":"t","s":[]}}`, + ) + }) +}