form_mapping.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. package binding
  2. import (
  3. "reflect"
  4. "strconv"
  5. "strings"
  6. "sync"
  7. "time"
  8. "github.com/pkg/errors"
  9. )
  10. // scache struct reflect type cache.
  11. var scache = &cache{
  12. data: make(map[reflect.Type]*sinfo),
  13. }
  14. type cache struct {
  15. data map[reflect.Type]*sinfo
  16. mutex sync.RWMutex
  17. }
  18. func (c *cache) get(obj reflect.Type) (s *sinfo) {
  19. var ok bool
  20. c.mutex.RLock()
  21. if s, ok = c.data[obj]; !ok {
  22. c.mutex.RUnlock()
  23. s = c.set(obj)
  24. return
  25. }
  26. c.mutex.RUnlock()
  27. return
  28. }
  29. func (c *cache) set(obj reflect.Type) (s *sinfo) {
  30. s = new(sinfo)
  31. tp := obj.Elem()
  32. for i := 0; i < tp.NumField(); i++ {
  33. fd := new(field)
  34. fd.tp = tp.Field(i)
  35. tag := fd.tp.Tag.Get("form")
  36. fd.name, fd.option = parseTag(tag)
  37. if defV := fd.tp.Tag.Get("default"); defV != "" {
  38. dv := reflect.New(fd.tp.Type).Elem()
  39. setWithProperType(fd.tp.Type.Kind(), []string{defV}, dv, fd.option)
  40. fd.hasDefault = true
  41. fd.defaultValue = dv
  42. }
  43. s.field = append(s.field, fd)
  44. }
  45. c.mutex.Lock()
  46. c.data[obj] = s
  47. c.mutex.Unlock()
  48. return
  49. }
  50. type sinfo struct {
  51. field []*field
  52. }
  53. type field struct {
  54. tp reflect.StructField
  55. name string
  56. option tagOptions
  57. hasDefault bool // if field had default value
  58. defaultValue reflect.Value // field default value
  59. }
  60. func mapForm(ptr interface{}, form map[string][]string) error {
  61. sinfo := scache.get(reflect.TypeOf(ptr))
  62. val := reflect.ValueOf(ptr).Elem()
  63. for i, fd := range sinfo.field {
  64. typeField := fd.tp
  65. structField := val.Field(i)
  66. if !structField.CanSet() {
  67. continue
  68. }
  69. structFieldKind := structField.Kind()
  70. inputFieldName := fd.name
  71. if inputFieldName == "" {
  72. inputFieldName = typeField.Name
  73. // if "form" tag is nil, we inspect if the field is a struct.
  74. // this would not make sense for JSON parsing but it does for a form
  75. // since data is flatten
  76. if structFieldKind == reflect.Struct {
  77. err := mapForm(structField.Addr().Interface(), form)
  78. if err != nil {
  79. return err
  80. }
  81. continue
  82. }
  83. }
  84. inputValue, exists := form[inputFieldName]
  85. if !exists {
  86. // Set the field as default value when the input value is not exist
  87. if fd.hasDefault {
  88. structField.Set(fd.defaultValue)
  89. }
  90. continue
  91. }
  92. // Set the field as default value when the input value is empty
  93. if fd.hasDefault && inputValue[0] == "" {
  94. structField.Set(fd.defaultValue)
  95. continue
  96. }
  97. if _, isTime := structField.Interface().(time.Time); isTime {
  98. if err := setTimeField(inputValue[0], typeField, structField); err != nil {
  99. return err
  100. }
  101. continue
  102. }
  103. if err := setWithProperType(typeField.Type.Kind(), inputValue, structField, fd.option); err != nil {
  104. return err
  105. }
  106. }
  107. return nil
  108. }
  109. func setWithProperType(valueKind reflect.Kind, val []string, structField reflect.Value, option tagOptions) error {
  110. switch valueKind {
  111. case reflect.Int:
  112. return setIntField(val[0], 0, structField)
  113. case reflect.Int8:
  114. return setIntField(val[0], 8, structField)
  115. case reflect.Int16:
  116. return setIntField(val[0], 16, structField)
  117. case reflect.Int32:
  118. return setIntField(val[0], 32, structField)
  119. case reflect.Int64:
  120. return setIntField(val[0], 64, structField)
  121. case reflect.Uint:
  122. return setUintField(val[0], 0, structField)
  123. case reflect.Uint8:
  124. return setUintField(val[0], 8, structField)
  125. case reflect.Uint16:
  126. return setUintField(val[0], 16, structField)
  127. case reflect.Uint32:
  128. return setUintField(val[0], 32, structField)
  129. case reflect.Uint64:
  130. return setUintField(val[0], 64, structField)
  131. case reflect.Bool:
  132. return setBoolField(val[0], structField)
  133. case reflect.Float32:
  134. return setFloatField(val[0], 32, structField)
  135. case reflect.Float64:
  136. return setFloatField(val[0], 64, structField)
  137. case reflect.String:
  138. structField.SetString(val[0])
  139. case reflect.Slice:
  140. if option.Contains("split") {
  141. val = strings.Split(val[0], ",")
  142. }
  143. filtered := filterEmpty(val)
  144. switch structField.Type().Elem().Kind() {
  145. case reflect.Int64:
  146. valSli := make([]int64, 0, len(filtered))
  147. for i := 0; i < len(filtered); i++ {
  148. d, err := strconv.ParseInt(filtered[i], 10, 64)
  149. if err != nil {
  150. return err
  151. }
  152. valSli = append(valSli, d)
  153. }
  154. structField.Set(reflect.ValueOf(valSli))
  155. case reflect.String:
  156. valSli := make([]string, 0, len(filtered))
  157. for i := 0; i < len(filtered); i++ {
  158. valSli = append(valSli, filtered[i])
  159. }
  160. structField.Set(reflect.ValueOf(valSli))
  161. default:
  162. sliceOf := structField.Type().Elem().Kind()
  163. numElems := len(filtered)
  164. slice := reflect.MakeSlice(structField.Type(), len(filtered), len(filtered))
  165. for i := 0; i < numElems; i++ {
  166. if err := setWithProperType(sliceOf, filtered[i:], slice.Index(i), ""); err != nil {
  167. return err
  168. }
  169. }
  170. structField.Set(slice)
  171. }
  172. default:
  173. return errors.New("Unknown type")
  174. }
  175. return nil
  176. }
  177. func setIntField(val string, bitSize int, field reflect.Value) error {
  178. if val == "" {
  179. val = "0"
  180. }
  181. intVal, err := strconv.ParseInt(val, 10, bitSize)
  182. if err == nil {
  183. field.SetInt(intVal)
  184. }
  185. return errors.WithStack(err)
  186. }
  187. func setUintField(val string, bitSize int, field reflect.Value) error {
  188. if val == "" {
  189. val = "0"
  190. }
  191. uintVal, err := strconv.ParseUint(val, 10, bitSize)
  192. if err == nil {
  193. field.SetUint(uintVal)
  194. }
  195. return errors.WithStack(err)
  196. }
  197. func setBoolField(val string, field reflect.Value) error {
  198. if val == "" {
  199. val = "false"
  200. }
  201. boolVal, err := strconv.ParseBool(val)
  202. if err == nil {
  203. field.SetBool(boolVal)
  204. }
  205. return nil
  206. }
  207. func setFloatField(val string, bitSize int, field reflect.Value) error {
  208. if val == "" {
  209. val = "0.0"
  210. }
  211. floatVal, err := strconv.ParseFloat(val, bitSize)
  212. if err == nil {
  213. field.SetFloat(floatVal)
  214. }
  215. return errors.WithStack(err)
  216. }
  217. func setTimeField(val string, structField reflect.StructField, value reflect.Value) error {
  218. timeFormat := structField.Tag.Get("time_format")
  219. if timeFormat == "" {
  220. return errors.New("Blank time format")
  221. }
  222. if val == "" {
  223. value.Set(reflect.ValueOf(time.Time{}))
  224. return nil
  225. }
  226. l := time.Local
  227. if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC {
  228. l = time.UTC
  229. }
  230. if locTag := structField.Tag.Get("time_location"); locTag != "" {
  231. loc, err := time.LoadLocation(locTag)
  232. if err != nil {
  233. return errors.WithStack(err)
  234. }
  235. l = loc
  236. }
  237. t, err := time.ParseInLocation(timeFormat, val, l)
  238. if err != nil {
  239. return errors.WithStack(err)
  240. }
  241. value.Set(reflect.ValueOf(t))
  242. return nil
  243. }
  244. func filterEmpty(val []string) []string {
  245. filtered := make([]string, 0, len(val))
  246. for _, v := range val {
  247. if v != "" {
  248. filtered = append(filtered, v)
  249. }
  250. }
  251. return filtered
  252. }