github.com/astaxie/beego@v1.12.3/context/param/parsers.go (about) 1 package param 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "strconv" 7 "strings" 8 "time" 9 ) 10 11 type paramParser interface { 12 parse(value string, toType reflect.Type) (interface{}, error) 13 } 14 15 func getParser(param *MethodParam, t reflect.Type) paramParser { 16 switch t.Kind() { 17 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 18 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 19 return intParser{} 20 case reflect.Slice: 21 if t.Elem().Kind() == reflect.Uint8 { //treat []byte as string 22 return stringParser{} 23 } 24 if param.in == body { 25 return jsonParser{} 26 } 27 elemParser := getParser(param, t.Elem()) 28 if elemParser == (jsonParser{}) { 29 return elemParser 30 } 31 return sliceParser(elemParser) 32 case reflect.Bool: 33 return boolParser{} 34 case reflect.String: 35 return stringParser{} 36 case reflect.Float32, reflect.Float64: 37 return floatParser{} 38 case reflect.Ptr: 39 elemParser := getParser(param, t.Elem()) 40 if elemParser == (jsonParser{}) { 41 return elemParser 42 } 43 return ptrParser(elemParser) 44 default: 45 if t.PkgPath() == "time" && t.Name() == "Time" { 46 return timeParser{} 47 } 48 return jsonParser{} 49 } 50 } 51 52 type parserFunc func(value string, toType reflect.Type) (interface{}, error) 53 54 func (f parserFunc) parse(value string, toType reflect.Type) (interface{}, error) { 55 return f(value, toType) 56 } 57 58 type boolParser struct { 59 } 60 61 func (p boolParser) parse(value string, toType reflect.Type) (interface{}, error) { 62 return strconv.ParseBool(value) 63 } 64 65 type stringParser struct { 66 } 67 68 func (p stringParser) parse(value string, toType reflect.Type) (interface{}, error) { 69 return value, nil 70 } 71 72 type intParser struct { 73 } 74 75 func (p intParser) parse(value string, toType reflect.Type) (interface{}, error) { 76 return strconv.Atoi(value) 77 } 78 79 type floatParser struct { 80 } 81 82 func (p floatParser) parse(value string, toType reflect.Type) (interface{}, error) { 83 if toType.Kind() == reflect.Float32 { 84 res, err := strconv.ParseFloat(value, 32) 85 if err != nil { 86 return nil, err 87 } 88 return float32(res), nil 89 } 90 return strconv.ParseFloat(value, 64) 91 } 92 93 type timeParser struct { 94 } 95 96 func (p timeParser) parse(value string, toType reflect.Type) (result interface{}, err error) { 97 result, err = time.Parse(time.RFC3339, value) 98 if err != nil { 99 result, err = time.Parse("2006-01-02", value) 100 } 101 return 102 } 103 104 type jsonParser struct { 105 } 106 107 func (p jsonParser) parse(value string, toType reflect.Type) (interface{}, error) { 108 pResult := reflect.New(toType) 109 v := pResult.Interface() 110 err := json.Unmarshal([]byte(value), v) 111 if err != nil { 112 return nil, err 113 } 114 return pResult.Elem().Interface(), nil 115 } 116 117 func sliceParser(elemParser paramParser) paramParser { 118 return parserFunc(func(value string, toType reflect.Type) (interface{}, error) { 119 values := strings.Split(value, ",") 120 result := reflect.MakeSlice(toType, 0, len(values)) 121 elemType := toType.Elem() 122 for _, v := range values { 123 parsedValue, err := elemParser.parse(v, elemType) 124 if err != nil { 125 return nil, err 126 } 127 result = reflect.Append(result, reflect.ValueOf(parsedValue)) 128 } 129 return result.Interface(), nil 130 }) 131 } 132 133 func ptrParser(elemParser paramParser) paramParser { 134 return parserFunc(func(value string, toType reflect.Type) (interface{}, error) { 135 parsedValue, err := elemParser.parse(value, toType.Elem()) 136 if err != nil { 137 return nil, err 138 } 139 newValPtr := reflect.New(toType.Elem()) 140 newVal := reflect.Indirect(newValPtr) 141 convertedVal, err := safeConvert(reflect.ValueOf(parsedValue), toType.Elem()) 142 if err != nil { 143 return nil, err 144 } 145 146 newVal.Set(convertedVal) 147 return newValPtr.Interface(), nil 148 }) 149 }