Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix issue #2482 #2789

Merged
merged 1 commit into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions net/ghttp/ghttp_z_unit_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,88 @@ func Test_Issue2334(t *testing.T) {
t.Assert(res.StatusCode, 304)
})
}

type CreateOrderReq struct {
g.Meta `path:"/order" tags:"订单" method:"put" summary:"创建订单"`
Details []*OrderDetail `p:"detail" v:"required#请输入订单详情" dc:"订单详情"`
}

type OrderDetail struct {
Name string `p:"name" v:"required#请输入物料名称" dc:"物料名称"`
Sn string `p:"sn" v:"required#请输入客户编号" dc:"客户编号"`
Images string `p:"images" dc:"图片"`
Desc string `p:"desc" dc:"备注"`
Number int `p:"number" v:"required#请输入数量" dc:"数量"`
Price float64 `p:"price" v:"required" dc:"单价"`
}

type CreateOrderRes struct{}
type OrderController struct{}

func (c *OrderController) CreateOrder(ctx context.Context, req *CreateOrderReq) (res *CreateOrderRes, err error) {
return
}

// https://github.com/gogf/gf/issues/2482
func Test_Issue2482(t *testing.T) {
s := g.Server(guid.S())
s.Group("/api/v2", func(group *ghttp.RouterGroup) {
group.Middleware(ghttp.MiddlewareHandlerResponse)
group.Bind(OrderController{})
})
s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()
time.Sleep(1000 * time.Millisecond)

c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
gtest.C(t, func(t *gtest.T) {
content := `
{
"detail": [
{
"images": "string",
"desc": "string",
"number": 0,
"price": 0
}
]
}
`
t.Assert(c.PutContent(ctx, "/api/v2/order", content), `{"code":51,"message":"请输入物料名称","data":null}`)
})
gtest.C(t, func(t *gtest.T) {
content := `
{
"detail": [
{
"images": "string",
"desc": "string",
"number": 0,
"name": "string",
"price": 0
}
]
}
`
t.Assert(c.PutContent(ctx, "/api/v2/order", content), `{"code":51,"message":"请输入客户编号","data":null}`)
})
gtest.C(t, func(t *gtest.T) {
content := `
{
"detail": [
{
"images": "string",
"desc": "string",
"number": 0,
"name": "string",
"sn": "string",
"price": 0
}
]
}
`
t.Assert(c.PutContent(ctx, "/api/v2/order", content), `{"code":0,"message":"","data":null}`)
})
}
27 changes: 18 additions & 9 deletions util/gvalid/gvalid_validator_check_struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,9 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error
// which have the most priority than `rules` and struct tag.
if msg, ok := v.messages.(CustomMsg); ok && len(msg) > 0 {
for k, msgName := range msg {
if a, ok := fieldToAliasNameMap[k]; ok {
if aliasName, ok := fieldToAliasNameMap[k]; ok {
// Overwrite the key of field name.
customMessage[a] = msgName
customMessage[aliasName] = msgName
} else {
customMessage[k] = msgName
}
Expand Down Expand Up @@ -245,13 +245,17 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error
}
}
} else {
// The `field.TagValue` is the alias name of field.Name().
// Eg, value from struct tag `p`.
if field.TagValue != "" {
fieldToAliasNameMap[field.Name()] = field.TagValue
}
switch field.OriginalKind() {
case reflect.Map, reflect.Struct, reflect.Slice, reflect.Array:
// Recursively check attribute slice/map.
_, value = gutil.MapPossibleItemByKey(inputParamMap, field.Name())
value = getPossibleValueFromMap(
inputParamMap, field.Name(), fieldToAliasNameMap[field.Name()],
)
if value == nil {
switch field.Kind() {
case reflect.Map, reflect.Ptr, reflect.Slice, reflect.Array:
Expand Down Expand Up @@ -279,12 +283,9 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error
// The following logic is the same as some of CheckMap but with sequence support.
for _, checkRuleItem := range checkRules {
if !checkRuleItem.IsMeta {
_, value = gutil.MapPossibleItemByKey(inputParamMap, checkRuleItem.Name)
if value == nil {
if aliasName := fieldToAliasNameMap[checkRuleItem.Name]; aliasName != "" {
_, value = gutil.MapPossibleItemByKey(inputParamMap, aliasName)
}
}
value = getPossibleValueFromMap(
inputParamMap, checkRuleItem.Name, fieldToAliasNameMap[checkRuleItem.Name],
)
}
// Empty json string checks according to mapping field kind.
if value != nil {
Expand Down Expand Up @@ -347,3 +348,11 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error
}
return nil
}

func getPossibleValueFromMap(inputParamMap map[string]interface{}, fieldName, aliasName string) (value interface{}) {
_, value = gutil.MapPossibleItemByKey(inputParamMap, fieldName)
if value == nil && aliasName != "" {
_, value = gutil.MapPossibleItemByKey(inputParamMap, aliasName)
}
return
}
Loading