form_mapping.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
  2. // Use of this source code is governed by a MIT style
  3. // license that can be found in the LICENSE file.
  4. package binding
  5. import (
  6. "errors"
  7. "reflect"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/gin-gonic/gin/internal/json"
  12. )
  13. var errUnknownType = errors.New("Unknown type")
  14. func mapUri(ptr interface{}, m map[string][]string) error {
  15. return mapFormByTag(ptr, m, "uri")
  16. }
  17. func mapForm(ptr interface{}, form map[string][]string) error {
  18. return mapFormByTag(ptr, form, "form")
  19. }
  20. var emptyField = reflect.StructField{}
  21. func mapFormByTag(ptr interface{}, form map[string][]string, tag string) error {
  22. _, err := mapping(reflect.ValueOf(ptr), emptyField, form, tag)
  23. return err
  24. }
  25. func mapping(value reflect.Value, field reflect.StructField, form map[string][]string, tag string) (bool, error) {
  26. var vKind = value.Kind()
  27. if vKind == reflect.Ptr {
  28. var isNew bool
  29. vPtr := value
  30. if value.IsNil() {
  31. isNew = true
  32. vPtr = reflect.New(value.Type().Elem())
  33. }
  34. isSetted, err := mapping(vPtr.Elem(), field, form, tag)
  35. if err != nil {
  36. return false, err
  37. }
  38. if isNew && isSetted {
  39. value.Set(vPtr)
  40. }
  41. return isSetted, nil
  42. }
  43. ok, err := tryToSetValue(value, field, form, tag)
  44. if err != nil {
  45. return false, err
  46. }
  47. if ok {
  48. return true, nil
  49. }
  50. if vKind == reflect.Struct {
  51. tValue := value.Type()
  52. var isSetted bool
  53. for i := 0; i < value.NumField(); i++ {
  54. if !value.Field(i).CanSet() {
  55. continue
  56. }
  57. ok, err := mapping(value.Field(i), tValue.Field(i), form, tag)
  58. if err != nil {
  59. return false, err
  60. }
  61. isSetted = isSetted || ok
  62. }
  63. return isSetted, nil
  64. }
  65. return false, nil
  66. }
  67. func tryToSetValue(value reflect.Value, field reflect.StructField, form map[string][]string, tag string) (bool, error) {
  68. var tagValue, defaultValue string
  69. var isDefaultExists bool
  70. tagValue = field.Tag.Get(tag)
  71. tagValue, opts := head(tagValue, ",")
  72. if tagValue == "-" { // just ignoring this field
  73. return false, nil
  74. }
  75. if tagValue == "" { // default value is FieldName
  76. tagValue = field.Name
  77. }
  78. if tagValue == "" { // when field is "emptyField" variable
  79. return false, nil
  80. }
  81. var opt string
  82. for len(opts) > 0 {
  83. opt, opts = head(opts, ",")
  84. k, v := head(opt, "=")
  85. switch k {
  86. case "default":
  87. isDefaultExists = true
  88. defaultValue = v
  89. }
  90. }
  91. vs, ok := form[tagValue]
  92. if !ok && !isDefaultExists {
  93. return false, nil
  94. }
  95. switch value.Kind() {
  96. case reflect.Slice:
  97. if !ok {
  98. vs = []string{defaultValue}
  99. }
  100. return true, setSlice(vs, value, field)
  101. default:
  102. var val string
  103. if !ok {
  104. val = defaultValue
  105. }
  106. if len(vs) > 0 {
  107. val = vs[0]
  108. }
  109. return true, setWithProperType(val, value, field)
  110. }
  111. }
  112. func setWithProperType(val string, value reflect.Value, field reflect.StructField) error {
  113. switch value.Kind() {
  114. case reflect.Int:
  115. return setIntField(val, 0, value)
  116. case reflect.Int8:
  117. return setIntField(val, 8, value)
  118. case reflect.Int16:
  119. return setIntField(val, 16, value)
  120. case reflect.Int32:
  121. return setIntField(val, 32, value)
  122. case reflect.Int64:
  123. switch value.Interface().(type) {
  124. case time.Duration:
  125. return setTimeDuration(val, value, field)
  126. }
  127. return setIntField(val, 64, value)
  128. case reflect.Uint:
  129. return setUintField(val, 0, value)
  130. case reflect.Uint8:
  131. return setUintField(val, 8, value)
  132. case reflect.Uint16:
  133. return setUintField(val, 16, value)
  134. case reflect.Uint32:
  135. return setUintField(val, 32, value)
  136. case reflect.Uint64:
  137. return setUintField(val, 64, value)
  138. case reflect.Bool:
  139. return setBoolField(val, value)
  140. case reflect.Float32:
  141. return setFloatField(val, 32, value)
  142. case reflect.Float64:
  143. return setFloatField(val, 64, value)
  144. case reflect.String:
  145. value.SetString(val)
  146. case reflect.Struct:
  147. switch value.Interface().(type) {
  148. case time.Time:
  149. return setTimeField(val, field, value)
  150. }
  151. return json.Unmarshal([]byte(val), value.Addr().Interface())
  152. case reflect.Map:
  153. return json.Unmarshal([]byte(val), value.Addr().Interface())
  154. default:
  155. return errUnknownType
  156. }
  157. return nil
  158. }
  159. func setIntField(val string, bitSize int, field reflect.Value) error {
  160. if val == "" {
  161. val = "0"
  162. }
  163. intVal, err := strconv.ParseInt(val, 10, bitSize)
  164. if err == nil {
  165. field.SetInt(intVal)
  166. }
  167. return err
  168. }
  169. func setUintField(val string, bitSize int, field reflect.Value) error {
  170. if val == "" {
  171. val = "0"
  172. }
  173. uintVal, err := strconv.ParseUint(val, 10, bitSize)
  174. if err == nil {
  175. field.SetUint(uintVal)
  176. }
  177. return err
  178. }
  179. func setBoolField(val string, field reflect.Value) error {
  180. if val == "" {
  181. val = "false"
  182. }
  183. boolVal, err := strconv.ParseBool(val)
  184. if err == nil {
  185. field.SetBool(boolVal)
  186. }
  187. return err
  188. }
  189. func setFloatField(val string, bitSize int, field reflect.Value) error {
  190. if val == "" {
  191. val = "0.0"
  192. }
  193. floatVal, err := strconv.ParseFloat(val, bitSize)
  194. if err == nil {
  195. field.SetFloat(floatVal)
  196. }
  197. return err
  198. }
  199. func setTimeField(val string, structField reflect.StructField, value reflect.Value) error {
  200. timeFormat := structField.Tag.Get("time_format")
  201. if timeFormat == "" {
  202. timeFormat = time.RFC3339
  203. }
  204. if val == "" {
  205. value.Set(reflect.ValueOf(time.Time{}))
  206. return nil
  207. }
  208. l := time.Local
  209. if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC {
  210. l = time.UTC
  211. }
  212. if locTag := structField.Tag.Get("time_location"); locTag != "" {
  213. loc, err := time.LoadLocation(locTag)
  214. if err != nil {
  215. return err
  216. }
  217. l = loc
  218. }
  219. t, err := time.ParseInLocation(timeFormat, val, l)
  220. if err != nil {
  221. return err
  222. }
  223. value.Set(reflect.ValueOf(t))
  224. return nil
  225. }
  226. func setSlice(vals []string, value reflect.Value, field reflect.StructField) error {
  227. slice := reflect.MakeSlice(value.Type(), len(vals), len(vals))
  228. for i, s := range vals {
  229. err := setWithProperType(s, slice.Index(i), field)
  230. if err != nil {
  231. return err
  232. }
  233. }
  234. value.Set(slice)
  235. return nil
  236. }
  237. func setTimeDuration(val string, value reflect.Value, field reflect.StructField) error {
  238. d, err := time.ParseDuration(val)
  239. if err != nil {
  240. return err
  241. }
  242. value.Set(reflect.ValueOf(d))
  243. return nil
  244. }
  245. func head(str, sep string) (head string, tail string) {
  246. idx := strings.Index(str, sep)
  247. if idx < 0 {
  248. return str, ""
  249. }
  250. return str[:idx], str[idx+len(sep):]
  251. }