gconv.go 6.2 KB

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