github.com/codingeasygo/util@v0.0.0-20231206062002-1ce2f004b7d9/attrvalid/atrrvalid.go (about) 1 package attrvalid 2 3 import ( 4 "database/sql" 5 "errors" 6 "fmt" 7 "math" 8 "net/http" 9 "net/url" 10 "reflect" 11 "regexp" 12 "strconv" 13 "strings" 14 15 "github.com/codingeasygo/util/attrscan" 16 "github.com/codingeasygo/util/converter" 17 ) 18 19 type ZeroChecker interface { 20 IsZero() bool 21 } 22 23 //EnumValider is interface to enum valid 24 type EnumValider interface { 25 EnumValid(v interface{}) error 26 } 27 28 //Validable is interface to define object can be valid by valid temple 29 type Validable interface { 30 ValidFormat(format string, args ...interface{}) error 31 } 32 33 //M is an map[string]interface{} which can be valid by valid temple 34 type M map[string]interface{} 35 36 //RawMap will return raw map 37 func (m M) RawMap() map[string]interface{} { 38 return m 39 } 40 41 //Get will return value by key 42 func (m M) Get(key string) (v interface{}, err error) { 43 return m[key], nil 44 } 45 46 //ValidFormat will valid args by format temple 47 func (m M) ValidFormat(format string, args ...interface{}) error { 48 return ValidAttrFormat(format, m, true, args...) 49 } 50 51 //MS is an map[string]string which can be valid by valid temple 52 type MS map[string]string 53 54 //Get will return value by key 55 func (m MS) Get(key string) (v interface{}, err error) { 56 return m[key], nil 57 } 58 59 //ValidFormat will valid args by format temple 60 func (m MS) ValidFormat(format string, args ...interface{}) error { 61 return ValidAttrFormat(format, m, true, args...) 62 } 63 64 //Values is an url.Values which can be valid by valid temple 65 type Values url.Values 66 67 //Get will return value by key 68 func (v Values) Get(key string) (val interface{}, err error) { 69 return url.Values(v).Get(key), nil 70 } 71 72 //ValidFormat will valid args by format temple 73 func (v Values) ValidFormat(format string, args ...interface{}) error { 74 return ValidAttrFormat(format, v, true, args...) 75 } 76 77 //QueryValidFormat will valid args by http request query 78 func QueryValidFormat(req *http.Request, format string, args ...interface{}) error { 79 return Values(req.URL.Query()).ValidFormat(format, args...) 80 } 81 82 //FormValidFormat will valid args by http request form 83 func FormValidFormat(req *http.Request, format string, args ...interface{}) error { 84 return Values(req.Form).ValidFormat(format, args...) 85 } 86 87 //PostFormValidFormat will valid args by http request post form 88 func PostFormValidFormat(req *http.Request, format string, args ...interface{}) error { 89 return Values(req.PostForm).ValidFormat(format, args...) 90 } 91 92 //RequestValidFormat will valid args by http request query/form/postform 93 func RequestValidFormat(req *http.Request, format string, args ...interface{}) error { 94 query := req.URL.Query() 95 getter := func(key string) (v interface{}, err error) { 96 val := query.Get(key) 97 if len(val) < 1 { 98 val = req.Form.Get(key) 99 } 100 if len(val) < 1 { 101 val = req.PostForm.Get(key) 102 } 103 v = val 104 return 105 } 106 return ValidAttrFormat(format, ValueGetterF(getter), true, args...) 107 } 108 109 func checkTemplateRequired(data interface{}, required bool, lts []string) (bool, error) { 110 zeroChecker, ok := data.(ZeroChecker) 111 if v := reflect.ValueOf(data); (ok && zeroChecker.IsZero()) || v.Kind() == reflect.Invalid || (v.IsZero() || reflect.Indirect(v).IsZero()) { 112 if (lts[0] == "R" || lts[0] == "r") && required { 113 return true, errors.New("data is empty") 114 } 115 return true, nil 116 } 117 // if v, ok := data.(string); data == nil || (ok && len(v) < 1) { //chekc the value required. 118 // if (lts[0] == "R" || lts[0] == "r") && required { 119 // return true, errors.New("data is empty") 120 // } 121 // return true, nil 122 // } 123 // if v, ok := data.([]interface{}); data == nil || (ok && len(v) < 1) { //chekc the value required. 124 // if (lts[0] == "R" || lts[0] == "r") && required { 125 // return true, errors.New("data is empty") 126 // } 127 // return true, nil 128 // } 129 return false, nil 130 } 131 132 func CompatibleType(typ reflect.Type) (ok bool) { 133 if typ == reflect.TypeOf(nil) { 134 return 135 } 136 switch typ.Kind() { 137 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 138 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 139 reflect.Float32, reflect.Float64, reflect.String: 140 ok = true 141 case reflect.Ptr, reflect.Slice: 142 ok = CompatibleType(typ.Elem()) 143 } 144 return 145 } 146 147 //ValidAttrTemple will valid the data to specified value by limit 148 // 149 // 150 //data: target value for valding 151 // 152 //valueType: target value type limit by <R or O>|<S or I or F> 153 // 154 // R is value must be having and valid 155 // 156 // O is vlaue can be empty or nil, but must be valid if it having value 157 // 158 // S:string value,I:integet value,F:float value 159 // 160 // example "R|F" is required float value 161 // 162 // example "O|F" is optional float value 163 // 164 // 165 //valueRange: taget value range limit by <O or R or P>:<limit pattern> 166 // 167 // O is value must be in options, all optional is seperated by - 168 // 169 // R is value must be in range by "start-end", or "start" to positive infinite or negative infinite to "-end" 170 // 171 // P is value must be matched by regex pattern 172 // 173 // example "O:1-2-3-4" is valid by value is in options 1-2-3-4) 174 // example "P:^.*\@.*$" is valid by string having "@" 175 // 176 //required: if true, ValidAttrTemple will return fail when require value is empty or nil, 177 //if false, ValidAttrTemple will return success although setting required for emppty/nil value 178 func ValidAttrTemple(data interface{}, valueType string, valueRange string, required bool, enum EnumValider) (interface{}, error) { 179 valueRange = strings.Replace(valueRange, "%N", ",", -1) 180 valueRange = strings.Replace(valueRange, "%%", "%", -1) 181 lts := strings.SplitN(valueType, "|", 2) //valid required type 182 if len(lts) < 2 { 183 return nil, fmt.Errorf("invalid type limit:%s", valueType) 184 } 185 lrs := strings.SplitN(valueRange, ":", 2) //valid value range. 186 if len(lrs) < 2 { 187 return nil, fmt.Errorf("invalid range limit:%s", valueRange) 188 } 189 if ret, err := checkTemplateRequired(data, required, lts); ret { //check required 190 return nil, err 191 } 192 // required = required && (lts[0] == "R" || lts[0] == "r") 193 //define the valid string function. 194 validStr := func(ds string) (interface{}, error) { 195 //check range limit. 196 switch lrs[0] { 197 case "o", "O": //option limit. 198 options := strings.Split(lrs[1], "~") 199 if converter.ArrayHaving(options, ds) { 200 return ds, nil 201 } 202 return nil, fmt.Errorf("invalid value(%s) for options(%s)", ds, lrs[1]) 203 case "l", "L": //length limit 204 slen := int64(len(ds)) 205 rgs := strings.Split(lrs[1], "~") 206 var beg, end int64 = 0, 0 207 var err error = nil 208 if len(rgs) > 0 && len(rgs[0]) > 0 { 209 beg, err = strconv.ParseInt(rgs[0], 10, 64) 210 if err != nil { 211 return nil, fmt.Errorf("invalid range begin number(%s)", rgs[0]) 212 } 213 } else { 214 beg = 0 215 } 216 if len(rgs) > 1 && len(rgs[1]) > 0 { 217 end, err = strconv.ParseInt(rgs[1], 10, 64) 218 if err != nil { 219 return nil, fmt.Errorf("invalid range end number option(%s)", rgs[1]) 220 } 221 } else { 222 end = math.MaxInt64 223 } 224 if beg < slen && end > slen { 225 return ds, nil 226 } 227 return nil, fmt.Errorf("string length must match %d<len<%d, but %d", beg, end, slen) 228 case "p", "P": //regex pattern limit 229 mched, err := regexp.MatchString(lrs[1], ds) 230 if err != nil { 231 return nil, err 232 } 233 if mched { 234 return ds, nil 235 } 236 return nil, fmt.Errorf("value(%s) not match regex(%s)", ds, lrs[1]) 237 case "e", "E": 238 if enum == nil { 239 return nil, fmt.Errorf("target is not enum able") 240 } 241 return ds, enum.EnumValid(ds) 242 case "n", "N": 243 return ds, nil 244 } 245 //unknow range limit type. 246 return nil, fmt.Errorf("invalid range limit %s for string", lrs[0]) 247 } 248 //define valid number function. 249 validNum := func(ds float64) (interface{}, error) { 250 //check range limit. 251 switch lrs[0] { 252 case "r", "R": 253 var beg, end float64 = 0, 0 254 var err error = nil 255 rgs := strings.Split(lrs[1], "~") 256 if len(rgs) > 0 && len(rgs[0]) > 0 { 257 beg, err = strconv.ParseFloat(rgs[0], 64) 258 if err != nil { 259 return nil, fmt.Errorf("invalid range begin number(%s)", rgs[0]) 260 } 261 } else { 262 beg = 0 263 } 264 endStr := "" 265 if len(rgs) > 1 && len(rgs[1]) > 0 { 266 end, err = strconv.ParseFloat(rgs[1], 64) 267 if err != nil { 268 return nil, fmt.Errorf("invalid range end number option(%s)", rgs[1]) 269 } 270 endStr = rgs[1] 271 } else { 272 end = math.MaxFloat64 273 endStr = "MaxFloat64" 274 } 275 if beg < ds && end > ds { 276 return ds, nil 277 } 278 return nil, fmt.Errorf("value must match %f<val<%v, but %v", beg, endStr, ds) 279 case "o", "O": 280 options := strings.Split(lrs[1], "~") 281 var oary []float64 282 for _, o := range options { //covert to float array. 283 v, err := strconv.ParseFloat(o, 64) 284 if err != nil { 285 return nil, fmt.Errorf("invalid number option(%s)", lrs[1]) 286 } 287 oary = append(oary, v) 288 } 289 if converter.ArrayHaving(oary, ds) { 290 return ds, nil 291 } 292 return nil, fmt.Errorf("invalid value(%f) for options(%s)", ds, lrs[1]) 293 case "e", "E": 294 if enum == nil { 295 return nil, fmt.Errorf("target is not enum able") 296 } 297 return ds, enum.EnumValid(ds) 298 case "n", "N": 299 return ds, nil 300 } 301 //unknow range limit type. 302 return nil, fmt.Errorf("invalid range limit %s for float", lrs[0]) 303 } 304 //define valid number function. 305 validInt := func(ds int64) (interface{}, error) { 306 //check range limit. 307 switch lrs[0] { 308 case "r", "R": 309 var beg, end int64 = 0, 0 310 var err error = nil 311 rgs := strings.Split(lrs[1], "~") 312 if len(rgs) > 0 && len(rgs[0]) > 0 { 313 beg, err = strconv.ParseInt(rgs[0], 10, 64) 314 if err != nil { 315 return nil, fmt.Errorf("invalid range begin number(%s)", rgs[0]) 316 } 317 } else { 318 beg = 0 319 } 320 endStr := "" 321 if len(rgs) > 1 && len(rgs[1]) > 0 { 322 end, err = strconv.ParseInt(rgs[1], 10, 64) 323 if err != nil { 324 return nil, fmt.Errorf("invalid range end number option(%s)", rgs[1]) 325 } 326 endStr = rgs[1] 327 } else { 328 end = math.MaxInt64 329 endStr = "MaxInt64" 330 } 331 if beg < ds && end > ds { 332 return ds, nil 333 } 334 return nil, fmt.Errorf("value must match %v<val<%v, but %v", beg, endStr, ds) 335 case "o", "O": 336 options := strings.Split(lrs[1], "~") 337 var oary []int64 338 for _, o := range options { //covert to float array. 339 v, err := strconv.ParseInt(o, 10, 64) 340 if err != nil { 341 return nil, fmt.Errorf("invalid number option(%s)", lrs[1]) 342 } 343 oary = append(oary, v) 344 } 345 if converter.ArrayHaving(oary, ds) { 346 return ds, nil 347 } 348 return nil, fmt.Errorf("invalid value(%v) for options(%s)", ds, lrs[1]) 349 case "e", "E": 350 if enum == nil { 351 return nil, fmt.Errorf("target is not enum able") 352 } 353 return ds, enum.EnumValid(ds) 354 case "n", "N": 355 return ds, nil 356 } 357 //unknow range limit type. 358 return nil, fmt.Errorf("invalid range limit %s for float", lrs[0]) 359 } 360 //define value type function 361 validValeuType := func(ds interface{}) (interface{}, error) { 362 switch lts[1] { 363 case "s", "S": 364 sval, _ := converter.StringVal(ds) 365 return validStr(sval) 366 case "i", "I": 367 ids, err := converter.Int64Val(ds) 368 if err != nil { 369 return nil, fmt.Errorf("invalid value(%s) for type(%s):%v", ds, lts[1], err) 370 } 371 return validInt(ids) 372 case "f", "F": 373 fds, err := converter.Float64Val(ds) 374 if err != nil { 375 return nil, fmt.Errorf("invalid value(%s) for type(%s):%v", ds, lts[1], err) 376 } 377 return validNum(fds) 378 } 379 return nil, fmt.Errorf("invalid value type:%s", lts[1]) 380 } 381 return validValeuType(data) 382 } 383 384 func validAttrTemple(data interface{}, temple string, parts []string, required bool, enum EnumValider) (val interface{}, err error) { 385 val, err = ValidAttrTemple(data, parts[1], parts[2], required, enum) 386 if err != nil { 387 err = fmt.Errorf("limit(%s),%s", temple, err.Error()) 388 if len(parts) > 3 { 389 err = errors.New(parts[3]) 390 } 391 } 392 return 393 } 394 395 //ValueSetter is interface to set value to target arg 396 type ValueSetter interface { 397 //Set the value 398 Set(value interface{}) error 399 } 400 401 //ValueSetterF is func for implment ValueSetter 402 type ValueSetterF func(interface{}) error 403 404 //Set will set value to arg 405 func (v ValueSetterF) Set(value interface{}) error { return v(value) } 406 407 //ValueGetter is inteface for using get the value by key 408 type ValueGetter interface { 409 //Get the value by key 410 Get(key string) (interface{}, error) 411 } 412 413 //ValueGetterF is func for implment ValueGetter 414 type ValueGetterF func(key string) (interface{}, error) 415 416 //Get will call the func 417 func (v ValueGetterF) Get(key string) (interface{}, error) { return v(key) } 418 419 //ValidAttrFormat will valid multi value by foramt template, return error if fail 420 // 421 //format is temple set is seperated by ";", general it is one line one temple end with ";" 422 // 423 // arg1,R|I,R:0; 424 // arg2,O|F,R:0; 425 // ... 426 // 427 //valueGetter is value getter by key 428 // 429 //required if true, ValidAttrTemple will return fail when require value is empty or nil, 430 //if false, ValidAttrTemple will return success although setting required for emppty/nil value 431 // 432 //args is variable list for store value, it must be go pointer 433 // 434 // var arg1 int 435 // var arg2 float64 436 // ValidAttrFormat(format,getter,&arg1,&arg2) 437 // 438 func ValidAttrFormat(format string, valueGetter ValueGetter, required bool, args ...interface{}) error { 439 format = regexp.MustCompile(`\/\/.*`).ReplaceAllString(format, "") 440 format = strings.Replace(format, "\n", "", -1) 441 format = strings.Trim(format, " \t;") 442 if len(format) < 1 { 443 return errors.New("format not found") 444 } 445 temples := strings.Split(format, ";") 446 if len(args) < 1 { 447 args = make([]interface{}, len(temples)) 448 } 449 if len(temples) != len(args) { 450 return errors.New("args count is not equal format count") 451 } 452 for idx, temple := range temples { 453 temple = strings.TrimSpace(temple) 454 parts := strings.SplitN(temple, ",", 4) 455 if len(parts) < 3 { 456 return fmt.Errorf("temple error:%s", temple) 457 } 458 sval, err := valueGetter.Get(parts[0]) 459 if err != nil { 460 return fmt.Errorf("get value by key %v fail with %v", parts[0], err) 461 } 462 var target interface{} 463 var targetValue reflect.Value 464 var targetKind reflect.Kind 465 var enum EnumValider 466 if args[idx] != nil { 467 target = args[idx] 468 targetValue = reflect.Indirect(reflect.ValueOf(target)) 469 targetKind = targetValue.Kind() 470 enum, _ = args[idx].(EnumValider) 471 } 472 checkValue := reflect.ValueOf(sval) 473 if checkValue.Kind() == reflect.Ptr && !checkValue.IsZero() { 474 sval = reflect.Indirect(reflect.ValueOf(sval)).Interface() 475 } 476 if targetKind != reflect.Slice { 477 rval, err := validAttrTemple(sval, temple, parts, required, enum) 478 if err != nil { 479 return err 480 } 481 if rval == nil { 482 continue 483 } 484 var setted bool 485 if target != nil && !CompatibleType(targetValue.Type()) { 486 if setter, ok := target.(ValueSetter); ok { 487 setted = true 488 err = setter.Set(rval) 489 } else if sc, ok := target.(sql.Scanner); ok { 490 setted = true 491 err = sc.Scan(rval) 492 } 493 } 494 if target != nil && !setted { 495 err = ValidSetValue(target, rval) 496 } 497 if err != nil { 498 return fmt.Errorf("set value to %v by key %v,%v fail with %v", reflect.TypeOf(target), parts[0], reflect.TypeOf(sval), err) 499 } 500 continue 501 } 502 if target != nil && !CompatibleType(targetValue.Type()) { 503 if setter, ok := target.(ValueSetter); ok { 504 _, err = validAttrTemple(sval, temple, parts, required, enum) 505 if err != nil { 506 return err 507 } 508 err = setter.Set(sval) 509 if err != nil { 510 return fmt.Errorf("set value to %v by key %v,%v fail with %v", reflect.TypeOf(target), parts[0], reflect.TypeOf(sval), err) 511 } 512 continue 513 } 514 if sc, ok := target.(sql.Scanner); ok { 515 _, err = validAttrTemple(sval, temple, parts, required, enum) 516 if err != nil { 517 return err 518 } 519 err = sc.Scan(sval) 520 if err != nil { 521 return fmt.Errorf("set value to %v by key %v,%v fail with %v", reflect.TypeOf(target), parts[0], reflect.TypeOf(sval), err) 522 } 523 continue 524 } 525 } 526 svals, _ := converter.ArrayValAll(sval, true) //ignore error 527 // if err != nil && err != converter.ErrNil { 528 // return err 529 // } 530 if ret, err := checkTemplateRequired(svals, required, strings.SplitN(parts[1], "|", 2)); ret { //check required 531 if err != nil { 532 return err 533 } 534 continue 535 } 536 var targetArray reflect.Value 537 if target != nil { 538 targetArray = targetValue 539 } 540 for _, sval = range svals { 541 rval, err := validAttrTemple(sval, temple, parts, required, enum) 542 if err != nil { 543 return err 544 } 545 if rval == nil { 546 continue 547 } 548 if targetArray.IsValid() { 549 tval, err := ValidValue(targetValue.Type().Elem(), rval) 550 if err != nil { 551 return err 552 } 553 targetArray = reflect.Append(targetArray, reflect.ValueOf(tval)) 554 } 555 } 556 if targetArray.IsValid() { 557 targetValue.Set(targetArray) 558 } 559 } 560 return nil 561 } 562 563 //ValidSetValue will convert src value to dst type and set it 564 func ValidSetValue(dst, src interface{}) error { 565 if sc, ok := dst.(sql.Scanner); ok { 566 return sc.Scan(src) 567 } 568 if setter, ok := dst.(ValueSetter); ok { 569 return setter.Set(src) 570 } 571 dstValue := reflect.Indirect(reflect.ValueOf(dst)) 572 val, err := ValidValue(dstValue.Type(), src) 573 if err == nil { 574 targetValue := reflect.ValueOf(val) 575 if targetValue.Type() == dstValue.Type() { 576 dstValue.Set(targetValue) 577 } else { 578 dstValue.Set(targetValue.Convert(dstValue.Type())) 579 } 580 } 581 return err 582 } 583 584 //ValidValue will convert src value to dst type and return it 585 func ValidValue(dst reflect.Type, src interface{}) (val interface{}, err error) { 586 srcType := reflect.TypeOf(src) 587 srcValue := reflect.ValueOf(src) 588 if srcType.Kind() == dst.Kind() { 589 return srcValue.Convert(dst).Interface(), nil 590 } 591 if dst.Kind() != reflect.String && srcValue.CanConvert(dst) { //skip string for int=>string is invalid 592 return srcValue.Convert(dst).Interface(), nil 593 } 594 var isptr = false 595 var kind = dst.Kind() 596 if kind == reflect.Ptr { 597 kind = dst.Elem().Kind() 598 isptr = true 599 } 600 var tiv int64 601 var tfv float64 602 var tsv string 603 switch kind { 604 case reflect.Int: 605 tiv, err = converter.Int64Val(src) 606 if err == nil { 607 target := int(tiv) 608 if isptr { 609 val = &target 610 } else { 611 val = target 612 } 613 } 614 case reflect.Int16: 615 tiv, err = converter.Int64Val(src) 616 if err == nil { 617 target := int16(tiv) 618 if isptr { 619 val = &target 620 } else { 621 val = target 622 } 623 } 624 case reflect.Int32: 625 tiv, err = converter.Int64Val(src) 626 if err == nil { 627 target := int32(tiv) 628 if isptr { 629 val = &target 630 } else { 631 val = target 632 } 633 } 634 case reflect.Int64: 635 tiv, err = converter.Int64Val(src) 636 if err == nil { 637 target := int64(tiv) 638 if isptr { 639 val = &target 640 } else { 641 val = target 642 } 643 } 644 case reflect.Uint: 645 tiv, err = converter.Int64Val(src) 646 if err == nil { 647 target := uint(tiv) 648 if isptr { 649 val = &target 650 } else { 651 val = target 652 } 653 } 654 case reflect.Uint16: 655 tiv, err = converter.Int64Val(src) 656 if err == nil { 657 target := uint16(tiv) 658 if isptr { 659 val = &target 660 } else { 661 val = target 662 } 663 } 664 case reflect.Uint32: 665 tiv, err = converter.Int64Val(src) 666 if err == nil { 667 target := uint32(tiv) 668 if isptr { 669 val = &target 670 } else { 671 val = target 672 } 673 } 674 case reflect.Uint64: 675 tiv, err = converter.Int64Val(src) 676 if err == nil { 677 target := uint64(tiv) 678 if isptr { 679 val = &target 680 } else { 681 val = target 682 } 683 } 684 case reflect.Float32: 685 tfv, err = converter.Float64Val(src) 686 if err == nil { 687 target := float32(tfv) 688 if isptr { 689 val = &target 690 } else { 691 val = target 692 } 693 } 694 case reflect.Float64: 695 tfv, err = converter.Float64Val(src) 696 if err == nil { 697 target := float64(tfv) 698 if isptr { 699 val = &target 700 } else { 701 val = target 702 } 703 } 704 case reflect.String: 705 tsv, err = converter.StringVal(src) 706 if isptr { 707 val = &tsv 708 } else { 709 val = tsv 710 } 711 default: 712 err = fmt.Errorf("not supported") 713 } 714 if err == nil { 715 return val, err 716 } 717 return nil, fmt.Errorf("parse kind(%v) value to kind(%v) value->%v", srcType.Kind(), dst, err) 718 } 719 720 type rawMapable interface { 721 RawMap() map[string]interface{} 722 } 723 724 //Struct is validable struct impl 725 type Struct struct { 726 Target interface{} 727 Required bool 728 Tag string 729 loaded map[string]interface{} 730 } 731 732 //NewStruct will return new struct 733 func NewStruct(target interface{}) (s *Struct) { 734 if reflect.TypeOf(target).Kind() != reflect.Ptr { 735 panic("target must be pointer") 736 } 737 s = &Struct{ 738 Target: target, 739 Required: true, 740 Tag: "json", 741 loaded: map[string]interface{}{}, 742 } 743 return 744 } 745 746 //Get will return field value by key 747 func (s *Struct) Get(key string) (value interface{}, err error) { 748 if len(s.loaded) < 1 { 749 value := reflect.ValueOf(s.Target).Elem() 750 vtype := reflect.TypeOf(s.Target).Elem() 751 for i := 0; i < vtype.NumField(); i++ { 752 valueField := value.Field(i) 753 typeField := vtype.Field(i) 754 if !typeField.IsExported() { 755 continue 756 } 757 tag := strings.SplitN(typeField.Tag.Get(s.Tag), ",", 2)[0] 758 targetValue := valueField.Interface() 759 if mv, ok := targetValue.(map[string]interface{}); ok { 760 targetValue = M(mv) 761 } else if mv, ok := targetValue.(rawMapable); ok { 762 targetValue = M(mv.RawMap()) 763 } else { 764 if typeField.Type.Kind() == reflect.Struct { 765 targetValue = NewStruct(valueField.Addr().Interface()) 766 } else if typeField.Type.Kind() == reflect.Ptr && typeField.Type.Elem().Kind() == reflect.Struct { 767 targetValue = NewStruct(valueField.Interface()) 768 } 769 } 770 s.loaded[typeField.Name] = targetValue 771 s.loaded[tag] = targetValue 772 } 773 } 774 key = strings.Trim(key, "/") 775 parts := strings.SplitN(key, "/", 2) 776 value = s.loaded[parts[0]] 777 if len(parts) < 2 || value == nil { 778 return 779 } 780 if getter, ok := value.(ValueGetter); ok { 781 value, err = getter.Get(parts[1]) 782 } 783 return 784 } 785 786 //ValidFormat will valid format to struct filed 787 func (s *Struct) ValidFormat(format string, args ...interface{}) error { 788 return ValidAttrFormat(format, s, s.Required, args...) 789 } 790 791 //ValidStructAttrFormat will valid struct by filed 792 func ValidStructAttrFormat(format string, target interface{}, required bool, args ...interface{}) error { 793 return ValidAttrFormat(format, NewStruct(target), required, args...) 794 } 795 796 //ValidFormat will check all supported type and run valid format 797 func ValidFormat(format string, target interface{}, args ...interface{}) error { 798 if getter, ok := target.(ValueGetter); ok { 799 return ValidAttrFormat(format, getter, true, args...) 800 } 801 if req, ok := target.(*http.Request); ok { 802 return QueryValidFormat(req, format, args...) 803 } 804 if val, ok := target.(url.Values); ok { 805 return Values(val).ValidFormat(format, args...) 806 } 807 if ms, ok := target.(map[string]string); ok { 808 return MS(ms).ValidFormat(format, args...) 809 } 810 if mv, ok := target.(map[string]interface{}); ok { 811 return M(mv).ValidFormat(format, args...) 812 } 813 if mv, ok := target.(rawMapable); ok { 814 return M(mv.RawMap()).ValidFormat(format, args...) 815 } 816 return NewStruct(target).ValidFormat(format, args...) 817 } 818 819 type Valider struct { 820 attrscan.Scanner 821 } 822 823 var Default = &Valider{ 824 Scanner: attrscan.Scanner{ 825 Tag: "json", 826 NameConv: func(on, name string, field reflect.StructField) string { 827 return name 828 }, 829 }, 830 } 831 832 func ValidArgs(target interface{}, filter string, args ...interface{}) (format string, args_ []interface{}) { 833 format, args_ = Default.ValidArgs(target, filter, args...) 834 return 835 } 836 837 func (v *Valider) addValidArgs(target interface{}, filter string, format string, args []interface{}) (format_ string, args_ []interface{}) { 838 format_, args_ = format, args 839 v.FilterFieldCall("valid", target, filter, func(fieldName, fieldFunc string, field reflect.StructField, value interface{}) { 840 valid := field.Tag.Get("valid") 841 if field.Type.Kind() == reflect.Struct && valid == "inline" { 842 format_, args_ = v.addValidArgs(value, filter, format_, args_) 843 return 844 } 845 if len(valid) < 1 || valid == "-" { 846 return 847 } 848 valid = strings.TrimSpace(valid) 849 if strings.HasSuffix(valid, ";") { 850 format_ += valid + "\n" 851 } else { 852 format_ += valid + ";\n" 853 } 854 args_ = append(args_, value) 855 }) 856 return 857 } 858 859 func (v *Valider) ValidArgs(target interface{}, filter string, args ...interface{}) (format string, args_ []interface{}) { 860 format, args_ = v.addValidArgs(target, filter, "", nil) 861 for _, arg := range args { 862 if v, ok := arg.(string); ok { 863 arg = strings.TrimSpace(v) 864 if strings.HasSuffix(v, ";") { 865 format += v + "\n" 866 } else { 867 format += v + ";\n" 868 } 869 } else { 870 args_ = append(args_, arg) 871 } 872 } 873 format = strings.TrimSpace(format) 874 return 875 } 876 877 func Valid(target interface{}, filter, optional string) (err error) { 878 err = Default.Valid(target, filter, optional) 879 return 880 } 881 882 func (v *Valider) Valid(target interface{}, filter, optional string) (err error) { 883 errList := []string{} 884 optional = strings.TrimSpace(optional) 885 isExc := strings.HasPrefix(optional, "^") 886 optional = strings.TrimPrefix(optional, "^") 887 optional = strings.Trim(optional, ",") 888 optional = "," + optional + "," 889 isRequired := func(fieldName string) bool { 890 if isExc { 891 return strings.Contains(optional, ","+fieldName+",") 892 } else { 893 return !strings.Contains(optional, ","+fieldName+",") 894 } 895 } 896 v.FilterFieldCall("valid", target, filter, func(fieldName, fieldFunc string, field reflect.StructField, value interface{}) { 897 valid := field.Tag.Get("valid") 898 if len(valid) < 1 { 899 return 900 } 901 valid = strings.TrimSpace(valid) 902 valid = strings.TrimSuffix(valid, ";") 903 parts := strings.SplitN(valid, ",", 4) 904 if len(parts) < 3 { 905 errList = append(errList, fmt.Sprintf("valid error:%s", valid)) 906 return 907 } 908 var xerr error 909 enum, _ := value.(EnumValider) 910 targetValue := reflect.Indirect(reflect.ValueOf(value)) 911 if targetValue.Kind() == reflect.Slice { 912 n := targetValue.Len() 913 for i := 0; i < n; i++ { 914 targetItem := targetValue.Index(i) 915 _, xerr = validAttrTemple(targetItem.Interface(), valid, parts, isRequired(fieldName), enum) 916 if xerr != nil { 917 break 918 } 919 } 920 if xerr == nil && n < 1 { 921 _, xerr = validAttrTemple(nil, valid, parts, isRequired(fieldName), enum) 922 } 923 } else { 924 _, xerr = validAttrTemple(targetValue.Interface(), valid, parts, isRequired(fieldName), enum) 925 } 926 if xerr != nil { 927 errList = append(errList, xerr.Error()) 928 } 929 }) 930 if len(errList) > 0 { 931 err = fmt.Errorf("%v", strings.Join(errList, "\n")) 932 } 933 return 934 }