gconv.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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 implements powerful and convenient converting functionality for any types of variables.
  7. //
  8. // This package should keep much less dependencies with other packages.
  9. package gconv
  10. import (
  11. "context"
  12. "fmt"
  13. "math"
  14. "reflect"
  15. "strconv"
  16. "strings"
  17. "time"
  18. "github.com/gogf/gf/v2/encoding/gbinary"
  19. "github.com/gogf/gf/v2/internal/intlog"
  20. "github.com/gogf/gf/v2/internal/json"
  21. "github.com/gogf/gf/v2/internal/reflection"
  22. "github.com/gogf/gf/v2/os/gtime"
  23. "github.com/gogf/gf/v2/util/gtag"
  24. )
  25. var (
  26. // Empty strings.
  27. emptyStringMap = map[string]struct{}{
  28. "": {},
  29. "0": {},
  30. "no": {},
  31. "off": {},
  32. "false": {},
  33. }
  34. // StructTagPriority defines the default priority tags for Map*/Struct* functions.
  35. // Note that, the `gconv/param` tags are used by old version of package.
  36. // It is strongly recommended using short tag `c/p` instead in the future.
  37. StructTagPriority = []string{
  38. gtag.GConv, gtag.Param, gtag.GConvShort, gtag.ParamShort, gtag.Json,
  39. }
  40. )
  41. // Byte converts `any` to byte.
  42. func Byte(any interface{}) byte {
  43. if v, ok := any.(byte); ok {
  44. return v
  45. }
  46. return Uint8(any)
  47. }
  48. // Bytes converts `any` to []byte.
  49. func Bytes(any interface{}) []byte {
  50. if any == nil {
  51. return nil
  52. }
  53. switch value := any.(type) {
  54. case string:
  55. return []byte(value)
  56. case []byte:
  57. return value
  58. default:
  59. if f, ok := value.(iBytes); ok {
  60. return f.Bytes()
  61. }
  62. originValueAndKind := reflection.OriginValueAndKind(any)
  63. switch originValueAndKind.OriginKind {
  64. case reflect.Map:
  65. bytes, err := json.Marshal(any)
  66. if err != nil {
  67. intlog.Errorf(context.TODO(), `%+v`, err)
  68. }
  69. return bytes
  70. case reflect.Array, reflect.Slice:
  71. var (
  72. ok = true
  73. bytes = make([]byte, originValueAndKind.OriginValue.Len())
  74. )
  75. for i := range bytes {
  76. int32Value := Int32(originValueAndKind.OriginValue.Index(i).Interface())
  77. if int32Value < 0 || int32Value > math.MaxUint8 {
  78. ok = false
  79. break
  80. }
  81. bytes[i] = byte(int32Value)
  82. }
  83. if ok {
  84. return bytes
  85. }
  86. }
  87. return gbinary.Encode(any)
  88. }
  89. }
  90. // Rune converts `any` to rune.
  91. func Rune(any interface{}) rune {
  92. if v, ok := any.(rune); ok {
  93. return v
  94. }
  95. return Int32(any)
  96. }
  97. // Runes converts `any` to []rune.
  98. func Runes(any interface{}) []rune {
  99. if v, ok := any.([]rune); ok {
  100. return v
  101. }
  102. return []rune(String(any))
  103. }
  104. // String converts `any` to string.
  105. // It's most commonly used converting function.
  106. func String(any interface{}) string {
  107. if any == nil {
  108. return ""
  109. }
  110. switch value := any.(type) {
  111. case int:
  112. return strconv.Itoa(value)
  113. case int8:
  114. return strconv.Itoa(int(value))
  115. case int16:
  116. return strconv.Itoa(int(value))
  117. case int32:
  118. return strconv.Itoa(int(value))
  119. case int64:
  120. return strconv.FormatInt(value, 10)
  121. case uint:
  122. return strconv.FormatUint(uint64(value), 10)
  123. case uint8:
  124. return strconv.FormatUint(uint64(value), 10)
  125. case uint16:
  126. return strconv.FormatUint(uint64(value), 10)
  127. case uint32:
  128. return strconv.FormatUint(uint64(value), 10)
  129. case uint64:
  130. return strconv.FormatUint(value, 10)
  131. case float32:
  132. return strconv.FormatFloat(float64(value), 'f', -1, 32)
  133. case float64:
  134. return strconv.FormatFloat(value, 'f', -1, 64)
  135. case bool:
  136. return strconv.FormatBool(value)
  137. case string:
  138. return value
  139. case []byte:
  140. return string(value)
  141. case time.Time:
  142. if value.IsZero() {
  143. return ""
  144. }
  145. return value.String()
  146. case *time.Time:
  147. if value == nil {
  148. return ""
  149. }
  150. return value.String()
  151. case gtime.Time:
  152. if value.IsZero() {
  153. return ""
  154. }
  155. return value.String()
  156. case *gtime.Time:
  157. if value == nil {
  158. return ""
  159. }
  160. return value.String()
  161. default:
  162. // Empty checks.
  163. if value == nil {
  164. return ""
  165. }
  166. if f, ok := value.(iString); ok {
  167. // If the variable implements the String() interface,
  168. // then use that interface to perform the conversion
  169. return f.String()
  170. }
  171. if f, ok := value.(iError); ok {
  172. // If the variable implements the Error() interface,
  173. // then use that interface to perform the conversion
  174. return f.Error()
  175. }
  176. // Reflect checks.
  177. var (
  178. rv = reflect.ValueOf(value)
  179. kind = rv.Kind()
  180. )
  181. switch kind {
  182. case reflect.Chan,
  183. reflect.Map,
  184. reflect.Slice,
  185. reflect.Func,
  186. reflect.Ptr,
  187. reflect.Interface,
  188. reflect.UnsafePointer:
  189. if rv.IsNil() {
  190. return ""
  191. }
  192. case reflect.String:
  193. return rv.String()
  194. }
  195. if kind == reflect.Ptr {
  196. return String(rv.Elem().Interface())
  197. }
  198. // Finally, we use json.Marshal to convert.
  199. if jsonContent, err := json.Marshal(value); err != nil {
  200. return fmt.Sprint(value)
  201. } else {
  202. return string(jsonContent)
  203. }
  204. }
  205. }
  206. // Bool converts `any` to bool.
  207. // It returns false if `any` is: false, "", 0, "false", "off", "no", empty slice/map.
  208. func Bool(any interface{}) bool {
  209. if any == nil {
  210. return false
  211. }
  212. switch value := any.(type) {
  213. case bool:
  214. return value
  215. case []byte:
  216. if _, ok := emptyStringMap[strings.ToLower(string(value))]; ok {
  217. return false
  218. }
  219. return true
  220. case string:
  221. if _, ok := emptyStringMap[strings.ToLower(value)]; ok {
  222. return false
  223. }
  224. return true
  225. default:
  226. if f, ok := value.(iBool); ok {
  227. return f.Bool()
  228. }
  229. rv := reflect.ValueOf(any)
  230. switch rv.Kind() {
  231. case reflect.Ptr:
  232. return !rv.IsNil()
  233. case reflect.Map:
  234. fallthrough
  235. case reflect.Array:
  236. fallthrough
  237. case reflect.Slice:
  238. return rv.Len() != 0
  239. case reflect.Struct:
  240. return true
  241. default:
  242. s := strings.ToLower(String(any))
  243. if _, ok := emptyStringMap[s]; ok {
  244. return false
  245. }
  246. return true
  247. }
  248. }
  249. }
  250. // checkJsonAndUnmarshalUseNumber checks if given `any` is JSON formatted string value and does converting using `json.UnmarshalUseNumber`.
  251. func checkJsonAndUnmarshalUseNumber(any interface{}, target interface{}) bool {
  252. switch r := any.(type) {
  253. case []byte:
  254. if json.Valid(r) {
  255. if err := json.UnmarshalUseNumber(r, &target); err != nil {
  256. return false
  257. }
  258. return true
  259. }
  260. case string:
  261. anyAsBytes := []byte(r)
  262. if json.Valid(anyAsBytes) {
  263. if err := json.UnmarshalUseNumber(anyAsBytes, &target); err != nil {
  264. return false
  265. }
  266. return true
  267. }
  268. }
  269. return false
  270. }