gconv_scan.go 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gconv
  7. import (
  8. "github.com/gogf/gf/errors/gcode"
  9. "github.com/gogf/gf/errors/gerror"
  10. "reflect"
  11. )
  12. // Scan automatically checks the type of `pointer` and converts `params` to `pointer`. It supports `pointer`
  13. // with type of `*map/*[]map/*[]*map/*struct/**struct/*[]struct/*[]*struct` for converting.
  14. //
  15. // It calls function `doMapToMap` internally if `pointer` is type of *map for converting.
  16. // It calls function `doMapToMaps` internally if `pointer` is type of *[]map/*[]*map for converting.
  17. // It calls function `doStruct` internally if `pointer` is type of *struct/**struct for converting.
  18. // It calls function `doStructs` internally if `pointer` is type of *[]struct/*[]*struct for converting.
  19. func Scan(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
  20. var (
  21. pointerType reflect.Type
  22. pointerKind reflect.Kind
  23. )
  24. if v, ok := pointer.(reflect.Value); ok {
  25. pointerType = v.Type()
  26. } else {
  27. pointerType = reflect.TypeOf(pointer)
  28. }
  29. if pointerType == nil {
  30. return gerror.NewCode(gcode.CodeInvalidParameter, "parameter pointer should not be nil")
  31. }
  32. pointerKind = pointerType.Kind()
  33. if pointerKind != reflect.Ptr {
  34. return gerror.NewCodef(gcode.CodeInvalidParameter, "params should be type of pointer, but got type: %v", pointerKind)
  35. }
  36. var (
  37. pointerElem = pointerType.Elem()
  38. pointerElemKind = pointerElem.Kind()
  39. keyToAttributeNameMapping map[string]string
  40. )
  41. if len(mapping) > 0 {
  42. keyToAttributeNameMapping = mapping[0]
  43. }
  44. switch pointerElemKind {
  45. case reflect.Map:
  46. return doMapToMap(params, pointer, mapping...)
  47. case reflect.Array, reflect.Slice:
  48. var (
  49. sliceElem = pointerElem.Elem()
  50. sliceElemKind = sliceElem.Kind()
  51. )
  52. for sliceElemKind == reflect.Ptr {
  53. sliceElem = sliceElem.Elem()
  54. sliceElemKind = sliceElem.Kind()
  55. }
  56. if sliceElemKind == reflect.Map {
  57. return doMapToMaps(params, pointer, mapping...)
  58. }
  59. return doStructs(params, pointer, keyToAttributeNameMapping, "")
  60. default:
  61. return doStruct(params, pointer, keyToAttributeNameMapping, "")
  62. }
  63. }
  64. // ScanDeep automatically calls StructDeep or StructsDeep function according to the type of
  65. // parameter `pointer` to implement the converting.
  66. //
  67. // It calls function StructDeep if `pointer` is type of *struct/**struct to do the converting.
  68. // It calls function StructsDeep if `pointer` is type of *[]struct/*[]*struct to do the converting.
  69. // Deprecated, use Scan instead.
  70. func ScanDeep(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
  71. t := reflect.TypeOf(pointer)
  72. k := t.Kind()
  73. if k != reflect.Ptr {
  74. return gerror.NewCodef(gcode.CodeInvalidParameter, "params should be type of pointer, but got: %v", k)
  75. }
  76. switch t.Elem().Kind() {
  77. case reflect.Array, reflect.Slice:
  78. return StructsDeep(params, pointer, mapping...)
  79. default:
  80. return StructDeep(params, pointer, mapping...)
  81. }
  82. }