1. form数据绑定结构体

本实例讲解的是form表单提交的数据绑定结构体,具体实现方法如下代码;

代码目录:

1129

-common

—common.go //是封装的代码

-main.go //是测试代码

代码的封装:

  1. // Package implements functions to decode values of a html form.
  2. package common
  3. import (
  4. "encoding"
  5. "encoding/json"
  6. "fmt"
  7. "net/url"
  8. "reflect"
  9. "strconv"
  10. "time"
  11. )
  12. const tagName = "kuteng"
  13. // pathMap holds the values of a map with its key and values correspondent
  14. type pathMap struct {
  15. ma reflect.Value
  16. key string
  17. value reflect.Value
  18. path string
  19. }
  20. // pathMaps holds the values for each key
  21. type pathMaps []*pathMap
  22. // find finds and gets the value by the given key
  23. func (m pathMaps) find(id reflect.Value, key string) *pathMap {
  24. for i := range m {
  25. if m[i].ma == id && m[i].key == key {
  26. return m[i]
  27. }
  28. }
  29. return nil
  30. }
  31. type Error struct {
  32. err error
  33. }
  34. func (s *Error) Error() string {
  35. return "kuteng: " + s.err.Error()
  36. }
  37. func (s Error) MarshalJSON() ([]byte, error) {
  38. return json.Marshal(s.err.Error())
  39. }
  40. // Cause implements the causer interface from github.com/pkg/errors.
  41. func (s *Error) Cause() error {
  42. return s.err
  43. }
  44. func newError(err error) *Error { return &Error{err} }
  45. // DecodeCustomTypeFunc is a function that indicate how should to decode a custom type
  46. type DecodeCustomTypeFunc func([]string) (interface{}, error)
  47. // DecodeCustomTypeField is a function registered for a specific field of the struct passed to the Decoder
  48. type DecodeCustomTypeField struct {
  49. field reflect.Value
  50. fun DecodeCustomTypeFunc
  51. }
  52. // DecodeCustomType fields for custom types
  53. type DecodeCustomType struct {
  54. fun DecodeCustomTypeFunc
  55. fields []*DecodeCustomTypeField
  56. }
  57. // Decoder the main to decode the values
  58. type Decoder struct {
  59. main reflect.Value
  60. formValues url.Values
  61. opts *DecoderOptions
  62. curr reflect.Value
  63. values []string
  64. path string
  65. field string
  66. bracket string
  67. //isKey bool
  68. maps pathMaps
  69. customTypes map[reflect.Type]*DecodeCustomType
  70. }
  71. // DecoderOptions options for decoding the values
  72. type DecoderOptions struct {
  73. // TagName indicates the tag name for decoding a value by the tag
  74. TagName string
  75. // PrefUnmarshalText indicates if should to give preference to UnmarshalText over custom type registered
  76. PrefUnmarshalText bool
  77. // IgnoreUnknownKeys controls the behaviour when the decoder encounters unknown keys in the map. If i is true and an unknown field is encountered, it is ignored. This is similar to how unknown keys are handled by encoding/json. If i is false then Decode will return an error. Note that any valid keys will still be decoded in to the target struct.
  78. IgnoreUnknownKeys bool
  79. }
  80. // RegisterCustomType It is the method responsible for register functions for decoding custom types
  81. func (dec *Decoder) RegisterCustomType(fn DecodeCustomTypeFunc, types []interface{}, fields []interface{}) *Decoder {
  82. if dec.customTypes == nil {
  83. dec.customTypes = make(map[reflect.Type]*DecodeCustomType, 100)
  84. }
  85. lenFields := len(fields)
  86. for i := range types {
  87. typ := reflect.TypeOf(types[i])
  88. if dec.customTypes[typ] == nil {
  89. dec.customTypes[typ] = &DecodeCustomType{fun: fn, fields: make([]*DecodeCustomTypeField, 0, lenFields)}
  90. }
  91. if lenFields > 0 {
  92. for j := range fields {
  93. val := reflect.ValueOf(fields[j])
  94. field := &DecodeCustomTypeField{field: val, fun: fn}
  95. dec.customTypes[typ].fields = append(dec.customTypes[typ].fields, field)
  96. }
  97. }
  98. }
  99. return dec
  100. }
  101. // NewDecoder creates a new instance of Decoder
  102. func NewDecoder(opts *DecoderOptions) *Decoder {
  103. dec := &Decoder{opts: opts}
  104. if dec.opts == nil {
  105. dec.opts = &DecoderOptions{}
  106. }
  107. if dec.opts.TagName == "" {
  108. dec.opts.TagName = tagName
  109. }
  110. return dec
  111. }
  112. // Decode decodes the url.Values into a element that must be a pointer to a type provided by argument
  113. func (dec Decoder) Decode(vs url.Values, dst interface{}) error {
  114. main := reflect.ValueOf(dst)
  115. if main.Kind() != reflect.Ptr {
  116. return newError(fmt.Errorf("the value passed for decode is not a pointer but a %v", main.Kind()))
  117. }
  118. dec.main = main.Elem()
  119. dec.formValues = vs
  120. return dec.init()
  121. }
  122. // Decode decodes the url.Values into a element that must be a pointer to a type provided by argument
  123. func Decode(vs url.Values, dst interface{}) error {
  124. main := reflect.ValueOf(dst)
  125. if main.Kind() != reflect.Ptr {
  126. return newError(fmt.Errorf("the value passed for decode is not a pointer but a %v", main.Kind()))
  127. }
  128. dec := &Decoder{
  129. main: main.Elem(),
  130. formValues: vs,
  131. opts: &DecoderOptions{
  132. TagName: tagName,
  133. },
  134. }
  135. return dec.init()
  136. }
  137. // init initializes the decoding
  138. func (dec Decoder) init() error {
  139. // iterate over the form's values and decode it
  140. for k, v := range dec.formValues {
  141. dec.path = k
  142. dec.values = v
  143. dec.curr = dec.main
  144. if err := dec.analyzePath(); err != nil {
  145. if dec.curr.Kind() == reflect.Struct && dec.opts.IgnoreUnknownKeys {
  146. continue
  147. }
  148. return err
  149. }
  150. }
  151. // set values of maps
  152. for _, v := range dec.maps {
  153. key := v.ma.Type().Key()
  154. ptr := false
  155. // check if the key implements the UnmarshalText interface
  156. var val reflect.Value
  157. if key.Kind() == reflect.Ptr {
  158. ptr = true
  159. val = reflect.New(key.Elem())
  160. } else {
  161. val = reflect.New(key).Elem()
  162. }
  163. // decode key
  164. dec.path = v.path
  165. dec.field = v.path
  166. dec.values = []string{v.key}
  167. dec.curr = val
  168. //dec.isKey = true
  169. if err := dec.decode(); err != nil {
  170. return err
  171. }
  172. // check if the key is a pointer or not. And if it is, then get its address
  173. if ptr && dec.curr.Kind() != reflect.Ptr {
  174. dec.curr = dec.curr.Addr()
  175. }
  176. // set key with its value
  177. v.ma.SetMapIndex(dec.curr, v.value)
  178. }
  179. return nil
  180. }
  181. // analyzePath analyzes the current path to walk through it
  182. func (dec *Decoder) analyzePath() (err error) {
  183. inBracket := false
  184. bracketClosed := false
  185. lastPos := 0
  186. endPos := 0
  187. // parse path
  188. for i, char := range []byte(dec.path) {
  189. if char == '[' && inBracket == false {
  190. // found an opening bracket
  191. bracketClosed = false
  192. inBracket = true
  193. dec.field = dec.path[lastPos:i]
  194. lastPos = i + 1
  195. continue
  196. } else if inBracket {
  197. // it is inside of bracket, so get its value
  198. if char == ']' {
  199. // found an closing bracket, so it will be recently close, so put as true the bracketClosed
  200. // and put as false inBracket and pass the value of bracket to dec.key
  201. inBracket = false
  202. bracketClosed = true
  203. dec.bracket = dec.path[lastPos:endPos]
  204. lastPos = i + 1
  205. if err = dec.traverse(); err != nil {
  206. return
  207. }
  208. } else {
  209. // still inside the bracket, so to save the end position
  210. endPos = i + 1
  211. }
  212. continue
  213. } else if !inBracket {
  214. // not found any bracket, so try found a field
  215. if char == '.' {
  216. // found a field, we need to know if the field is next of a closing bracket,
  217. // for example: [0].Field
  218. if bracketClosed {
  219. bracketClosed = false
  220. lastPos = i + 1
  221. continue
  222. }
  223. // found a field, but is not next of a closing bracket, for example: Field1.Field2
  224. dec.field = dec.path[lastPos:i]
  225. //dec.field = tmp[:i]
  226. lastPos = i + 1
  227. if err = dec.traverse(); err != nil {
  228. return
  229. }
  230. }
  231. continue
  232. }
  233. }
  234. // last field of path
  235. dec.field = dec.path[lastPos:]
  236. return dec.end()
  237. }
  238. // walk traverses the current path until to the last field
  239. func (dec *Decoder) traverse() error {
  240. // check if there is field, if is so, then it should be struct or map (access by .)
  241. if dec.field != "" {
  242. // check if is a struct or map
  243. switch dec.curr.Kind() {
  244. case reflect.Struct:
  245. if err := dec.findStructField(); err != nil {
  246. return err
  247. }
  248. case reflect.Map:
  249. dec.traverseInMap(true)
  250. }
  251. dec.field = ""
  252. }
  253. // check if is a interface and it is not nil. This mean that the interface
  254. // has a struct, map or slice as value
  255. if dec.curr.Kind() == reflect.Interface && !dec.curr.IsNil() {
  256. dec.curr = dec.curr.Elem()
  257. }
  258. // check if it is a pointer
  259. if dec.curr.Kind() == reflect.Ptr {
  260. if dec.curr.IsNil() {
  261. dec.curr.Set(reflect.New(dec.curr.Type().Elem()))
  262. }
  263. dec.curr = dec.curr.Elem()
  264. }
  265. // check if there is access to slice/array or map (access by [])
  266. if dec.bracket != "" {
  267. switch dec.curr.Kind() {
  268. case reflect.Array:
  269. index, err := strconv.Atoi(dec.bracket)
  270. if err != nil {
  271. return newError(fmt.Errorf("the index of array is not a number in the field \"%v\" of path \"%v\"", dec.field, dec.path))
  272. }
  273. dec.curr = dec.curr.Index(index)
  274. case reflect.Slice:
  275. index, err := strconv.Atoi(dec.bracket)
  276. if err != nil {
  277. return newError(fmt.Errorf("the index of slice is not a number in the field \"%v\" of path \"%v\"", dec.field, dec.path))
  278. }
  279. if dec.curr.Len() <= index {
  280. dec.expandSlice(index + 1)
  281. }
  282. dec.curr = dec.curr.Index(index)
  283. case reflect.Map:
  284. dec.traverseInMap(false)
  285. default:
  286. return newError(fmt.Errorf("the field \"%v\" in path \"%v\" has a index for array but it is a %v", dec.field, dec.path, dec.curr.Kind()))
  287. }
  288. dec.bracket = ""
  289. }
  290. return nil
  291. }
  292. // walkMap puts in d.curr the map concrete for decode the current value
  293. func (dec *Decoder) traverseInMap(byField bool) {
  294. n := dec.curr.Type()
  295. makeAndAppend := func() {
  296. if dec.maps == nil {
  297. dec.maps = make(pathMaps, 0, 500)
  298. }
  299. m := reflect.New(n.Elem()).Elem()
  300. if byField {
  301. dec.maps = append(dec.maps, &pathMap{dec.curr, dec.field, m, dec.path})
  302. } else {
  303. dec.maps = append(dec.maps, &pathMap{dec.curr, dec.bracket, m, dec.path})
  304. }
  305. dec.curr = m
  306. }
  307. if dec.curr.IsNil() {
  308. // map is nil
  309. dec.curr.Set(reflect.MakeMap(n))
  310. makeAndAppend()
  311. } else {
  312. // map is not nil, so try find value by the key
  313. var a *pathMap
  314. if byField {
  315. a = dec.maps.find(dec.curr, dec.field)
  316. } else {
  317. a = dec.maps.find(dec.curr, dec.bracket)
  318. }
  319. if a == nil {
  320. // the key not exists
  321. makeAndAppend()
  322. } else {
  323. dec.curr = a.value
  324. }
  325. }
  326. }
  327. // end finds the last field for decode its value correspondent
  328. func (dec *Decoder) end() error {
  329. switch dec.curr.Kind() {
  330. case reflect.Struct:
  331. if err := dec.findStructField(); err != nil {
  332. return err
  333. }
  334. case reflect.Map:
  335. // leave backward compatibility for access to maps by .
  336. dec.traverseInMap(true)
  337. }
  338. return dec.decode()
  339. }
  340. // decode sets the value in the field
  341. func (dec *Decoder) decode() error {
  342. // check if has UnmarshalText method or a custom function to decode it
  343. if dec.opts.PrefUnmarshalText {
  344. if ok, err := dec.isUnmarshalText(dec.curr); ok || err != nil {
  345. return err
  346. }
  347. if ok, err := dec.isCustomType(); ok || err != nil {
  348. return err
  349. }
  350. } else {
  351. if ok, err := dec.isCustomType(); ok || err != nil {
  352. return err
  353. }
  354. if ok, err := dec.isUnmarshalText(dec.curr); ok || err != nil {
  355. return err
  356. }
  357. }
  358. switch dec.curr.Kind() {
  359. case reflect.Array:
  360. if dec.bracket == "" {
  361. // not has index, so to decode all values in the slice
  362. if err := dec.setValues(); err != nil {
  363. return err
  364. }
  365. } else {
  366. // has index, so to decode value by index indicated
  367. index, err := strconv.Atoi(dec.bracket)
  368. if err != nil {
  369. return newError(fmt.Errorf("the index of array is not a number in the field \"%v\" of path \"%v\"", dec.field, dec.path))
  370. }
  371. dec.curr = dec.curr.Index(index)
  372. return dec.decode()
  373. }
  374. case reflect.Slice:
  375. if dec.bracket == "" {
  376. // not has index, so to decode all values in the slice
  377. // only for slices
  378. dec.expandSlice(len(dec.values))
  379. if err := dec.setValues(); err != nil {
  380. return err
  381. }
  382. } else {
  383. // has index, so to decode value by index indicated
  384. index, err := strconv.Atoi(dec.bracket)
  385. if err != nil {
  386. return newError(fmt.Errorf("the index of slice is not a number in the field \"%v\" of path \"%v\"", dec.field, dec.path))
  387. }
  388. // only for slices
  389. if dec.curr.Len() <= index {
  390. dec.expandSlice(index + 1)
  391. }
  392. dec.curr = dec.curr.Index(index)
  393. return dec.decode()
  394. }
  395. case reflect.String:
  396. dec.curr.SetString(dec.values[0])
  397. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  398. if num, err := strconv.ParseInt(dec.values[0], 10, 64); err != nil {
  399. return newError(fmt.Errorf("the value of field \"%v\" in path \"%v\" should be a valid signed integer number", dec.field, dec.path))
  400. } else {
  401. dec.curr.SetInt(num)
  402. }
  403. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  404. if num, err := strconv.ParseUint(dec.values[0], 10, 64); err != nil {
  405. return newError(fmt.Errorf("the value of field \"%v\" in path \"%v\" should be a valid unsigned integer number", dec.field, dec.path))
  406. } else {
  407. dec.curr.SetUint(num)
  408. }
  409. case reflect.Float32, reflect.Float64:
  410. if num, err := strconv.ParseFloat(dec.values[0], dec.curr.Type().Bits()); err != nil {
  411. return newError(fmt.Errorf("the value of field \"%v\" in path \"%v\" should be a valid float number", dec.field, dec.path))
  412. } else {
  413. dec.curr.SetFloat(num)
  414. }
  415. case reflect.Bool:
  416. switch dec.values[0] {
  417. case "true", "on", "1", "checked":
  418. dec.curr.SetBool(true)
  419. default:
  420. dec.curr.SetBool(false)
  421. return nil
  422. }
  423. case reflect.Interface:
  424. dec.curr.Set(reflect.ValueOf(dec.values[0]))
  425. case reflect.Ptr:
  426. n := reflect.New(dec.curr.Type().Elem())
  427. if dec.curr.CanSet() {
  428. dec.curr.Set(n)
  429. } else {
  430. dec.curr.Elem().Set(n.Elem())
  431. }
  432. dec.curr = dec.curr.Elem()
  433. return dec.decode()
  434. case reflect.Struct:
  435. switch dec.curr.Interface().(type) {
  436. case time.Time:
  437. var t time.Time
  438. // if the value is empty then no to try to parse it and leave "t" as a zero value to set it in the field
  439. if dec.values[0] != "" {
  440. var err error
  441. t, err = time.Parse("2006-01-02", dec.values[0])
  442. if err != nil {
  443. return newError(fmt.Errorf("the value of field \"%v\" in path \"%v\" is not a valid datetime", dec.field, dec.path))
  444. }
  445. }
  446. dec.curr.Set(reflect.ValueOf(t))
  447. case url.URL:
  448. u, err := url.Parse(dec.values[0])
  449. if err != nil {
  450. return newError(fmt.Errorf("the value of field \"%v\" in path \"%v\" is not a valid url", dec.field, dec.path))
  451. }
  452. dec.curr.Set(reflect.ValueOf(*u))
  453. default:
  454. if dec.opts.IgnoreUnknownKeys {
  455. return nil
  456. }
  457. num := dec.curr.NumField()
  458. for i := 0; i < num; i++ {
  459. field := dec.curr.Type().Field(i)
  460. tag := field.Tag.Get(dec.opts.TagName)
  461. if tag == "-" {
  462. // skip this field
  463. return nil
  464. }
  465. }
  466. return newError(fmt.Errorf("not supported type for field \"%v\" in path \"%v\". Maybe you should to include it the UnmarshalText interface or register it using custom type?", dec.field, dec.path))
  467. }
  468. default:
  469. if dec.opts.IgnoreUnknownKeys {
  470. return nil
  471. }
  472. return newError(fmt.Errorf("not supported type for field \"%v\" in path \"%v\"", dec.field, dec.path))
  473. }
  474. return nil
  475. }
  476. // findStructField finds a field by its name, if it is not found,
  477. // then retry the search examining the tag "formam" of every field of struct
  478. func (dec *Decoder) findStructField() error {
  479. var anon reflect.Value
  480. num := dec.curr.NumField()
  481. for i := 0; i < num; i++ {
  482. field := dec.curr.Type().Field(i)
  483. if field.Name == dec.field {
  484. tag := field.Tag.Get(dec.opts.TagName)
  485. if tag == "-" {
  486. // skip this field
  487. return nil
  488. }
  489. // check if the field's name is equal
  490. dec.curr = dec.curr.Field(i)
  491. return nil
  492. } else if field.Anonymous {
  493. // if the field is a anonymous struct, then iterate over its fields
  494. tmp := dec.curr
  495. dec.curr = dec.curr.FieldByIndex(field.Index)
  496. if dec.curr.Kind() == reflect.Ptr {
  497. if dec.curr.IsNil() {
  498. dec.curr.Set(reflect.New(dec.curr.Type().Elem()))
  499. }
  500. dec.curr = dec.curr.Elem()
  501. }
  502. if err := dec.findStructField(); err != nil {
  503. dec.curr = tmp
  504. continue
  505. }
  506. // field in anonymous struct is found,
  507. // but first it should found the field in the rest of struct
  508. // (a field with same name in the current struct should have preference over anonymous struct)
  509. anon = dec.curr
  510. dec.curr = tmp
  511. } else if dec.field == field.Tag.Get(dec.opts.TagName) {
  512. // is not found yet, then retry by its tag name "formam"
  513. dec.curr = dec.curr.Field(i)
  514. return nil
  515. }
  516. }
  517. if anon.IsValid() {
  518. dec.curr = anon
  519. return nil
  520. }
  521. if dec.opts.IgnoreUnknownKeys {
  522. return nil
  523. }
  524. return newError(fmt.Errorf("not found the field \"%v\" in the path \"%v\"", dec.field, dec.path))
  525. }
  526. // expandSlice expands the length and capacity of the current slice
  527. func (dec *Decoder) expandSlice(length int) {
  528. n := reflect.MakeSlice(dec.curr.Type(), length, length)
  529. reflect.Copy(n, dec.curr)
  530. dec.curr.Set(n)
  531. }
  532. // setValues set the values in current slice/array
  533. func (dec *Decoder) setValues() error {
  534. tmp := dec.curr // hold current field
  535. for i, v := range dec.values {
  536. dec.curr = tmp.Index(i)
  537. dec.values[0] = v
  538. if err := dec.decode(); err != nil {
  539. return err
  540. }
  541. }
  542. return nil
  543. }
  544. // isCustomType checks if the field's type to decode has a custom type registered
  545. func (dec *Decoder) isCustomType() (bool, error) {
  546. if dec.customTypes == nil {
  547. return false, nil
  548. }
  549. if v, ok := dec.customTypes[dec.curr.Type()]; ok {
  550. if len(v.fields) > 0 {
  551. for i := range v.fields {
  552. // check if the current field is registered
  553. // in the fields of the custom type
  554. if v.fields[i].field.Elem() == dec.curr {
  555. va, err := v.fields[i].fun(dec.values)
  556. if err != nil {
  557. return true, err
  558. }
  559. dec.curr.Set(reflect.ValueOf(va))
  560. return true, nil
  561. }
  562. }
  563. }
  564. // check if the default function exists for fields not specific
  565. if v.fun != nil {
  566. va, err := v.fun(dec.values)
  567. if err != nil {
  568. return true, err
  569. }
  570. dec.curr.Set(reflect.ValueOf(va))
  571. return true, nil
  572. }
  573. }
  574. return false, nil
  575. }
  576. var (
  577. typeTime = reflect.TypeOf(time.Time{})
  578. typeTimePtr = reflect.TypeOf(&time.Time{})
  579. )
  580. // isUnmarshalText returns a boolean and error. The boolean is true if the
  581. // field's type implements TextUnmarshaler, and false if not.
  582. func (dec *Decoder) isUnmarshalText(v reflect.Value) (bool, error) {
  583. // check if implements the interface
  584. m, ok := v.Interface().(encoding.TextUnmarshaler)
  585. addr := v.CanAddr()
  586. if !ok && !addr {
  587. return false, nil
  588. } else if addr {
  589. return dec.isUnmarshalText(v.Addr())
  590. }
  591. // skip if the type is time.Time
  592. n := v.Type()
  593. if n.ConvertibleTo(typeTime) || n.ConvertibleTo(typeTimePtr) {
  594. return false, nil
  595. }
  596. // return result
  597. return true, m.UnmarshalText([]byte(dec.values[0]))
  598. }

代码的测试:

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "github.com/student/1129/common"
  6. )
  7. //Product Product定义一个结构体
  8. type Product struct {
  9. ID int64 `json:"id" sql:"id" kuteng:"id"`
  10. ProductClass string `json:"ProductClass" sql:"ProductClass" kuteng:"ProductClass"`
  11. ProductName string `json:"ProductName" sql:"productName" kuteng:"productName"`
  12. ProductNum int64 `json:"ProductNum" sql:"productNum" kuteng:"productNum"`
  13. ProductImage string `json:"ProductImage" sql:"productImage" kuteng:"productImage"`
  14. ProductURL string `json:"ProductUrl" sql:"productUrl" kuteng:"productUrl"`
  15. }
  16. func main() {
  17. product :=&Product{}
  18. //这块是表单提交的数据
  19. p.Ctx.Request().ParseForm()
  20. dec := common.NewDecoder(&common.DecoderOptions{TagName:"kuteng"})
  21. if err:= dec.Decode(p.Ctx.Request().Form,product);err!=nil {
  22. fmt.Println("绑定失败")
  23. }
  24. }