gconv_convert.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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. "reflect"
  9. "time"
  10. "github.com/gogf/gf/v2/os/gtime"
  11. )
  12. // Convert converts the variable `fromValue` to the type `toTypeName`, the type `toTypeName` is specified by string.
  13. //
  14. // The optional parameter `extraParams` is used for additional necessary parameter for this conversion.
  15. // It supports common basic types conversion as its conversion based on type name string.
  16. func Convert(fromValue interface{}, toTypeName string, extraParams ...interface{}) interface{} {
  17. return doConvert(doConvertInput{
  18. FromValue: fromValue,
  19. ToTypeName: toTypeName,
  20. ReferValue: nil,
  21. Extra: extraParams,
  22. })
  23. }
  24. // ConvertWithRefer converts the variable `fromValue` to the type referred by value `referValue`.
  25. //
  26. // The optional parameter `extraParams` is used for additional necessary parameter for this conversion.
  27. // It supports common basic types conversion as its conversion based on type name string.
  28. func ConvertWithRefer(fromValue interface{}, referValue interface{}, extraParams ...interface{}) interface{} {
  29. var referValueRf reflect.Value
  30. if v, ok := referValue.(reflect.Value); ok {
  31. referValueRf = v
  32. } else {
  33. referValueRf = reflect.ValueOf(referValue)
  34. }
  35. return doConvert(doConvertInput{
  36. FromValue: fromValue,
  37. ToTypeName: referValueRf.Type().String(),
  38. ReferValue: referValue,
  39. Extra: extraParams,
  40. })
  41. }
  42. type doConvertInput struct {
  43. FromValue interface{} // Value that is converted from.
  44. ToTypeName string // Target value type name in string.
  45. ReferValue interface{} // Referred value, a value in type `ToTypeName`. Note that its type might be reflect.Value.
  46. Extra []interface{} // Extra values for implementing the converting.
  47. // Marks that the value is already converted and set to `ReferValue`. Caller can ignore the returned result.
  48. // It is an attribute for internal usage purpose.
  49. alreadySetToReferValue bool
  50. }
  51. // doConvert does commonly use types converting.
  52. func doConvert(in doConvertInput) (convertedValue interface{}) {
  53. switch in.ToTypeName {
  54. case "int":
  55. return Int(in.FromValue)
  56. case "*int":
  57. if _, ok := in.FromValue.(*int); ok {
  58. return in.FromValue
  59. }
  60. v := Int(in.FromValue)
  61. return &v
  62. case "int8":
  63. return Int8(in.FromValue)
  64. case "*int8":
  65. if _, ok := in.FromValue.(*int8); ok {
  66. return in.FromValue
  67. }
  68. v := Int8(in.FromValue)
  69. return &v
  70. case "int16":
  71. return Int16(in.FromValue)
  72. case "*int16":
  73. if _, ok := in.FromValue.(*int16); ok {
  74. return in.FromValue
  75. }
  76. v := Int16(in.FromValue)
  77. return &v
  78. case "int32":
  79. return Int32(in.FromValue)
  80. case "*int32":
  81. if _, ok := in.FromValue.(*int32); ok {
  82. return in.FromValue
  83. }
  84. v := Int32(in.FromValue)
  85. return &v
  86. case "int64":
  87. return Int64(in.FromValue)
  88. case "*int64":
  89. if _, ok := in.FromValue.(*int64); ok {
  90. return in.FromValue
  91. }
  92. v := Int64(in.FromValue)
  93. return &v
  94. case "uint":
  95. return Uint(in.FromValue)
  96. case "*uint":
  97. if _, ok := in.FromValue.(*uint); ok {
  98. return in.FromValue
  99. }
  100. v := Uint(in.FromValue)
  101. return &v
  102. case "uint8":
  103. return Uint8(in.FromValue)
  104. case "*uint8":
  105. if _, ok := in.FromValue.(*uint8); ok {
  106. return in.FromValue
  107. }
  108. v := Uint8(in.FromValue)
  109. return &v
  110. case "uint16":
  111. return Uint16(in.FromValue)
  112. case "*uint16":
  113. if _, ok := in.FromValue.(*uint16); ok {
  114. return in.FromValue
  115. }
  116. v := Uint16(in.FromValue)
  117. return &v
  118. case "uint32":
  119. return Uint32(in.FromValue)
  120. case "*uint32":
  121. if _, ok := in.FromValue.(*uint32); ok {
  122. return in.FromValue
  123. }
  124. v := Uint32(in.FromValue)
  125. return &v
  126. case "uint64":
  127. return Uint64(in.FromValue)
  128. case "*uint64":
  129. if _, ok := in.FromValue.(*uint64); ok {
  130. return in.FromValue
  131. }
  132. v := Uint64(in.FromValue)
  133. return &v
  134. case "float32":
  135. return Float32(in.FromValue)
  136. case "*float32":
  137. if _, ok := in.FromValue.(*float32); ok {
  138. return in.FromValue
  139. }
  140. v := Float32(in.FromValue)
  141. return &v
  142. case "float64":
  143. return Float64(in.FromValue)
  144. case "*float64":
  145. if _, ok := in.FromValue.(*float64); ok {
  146. return in.FromValue
  147. }
  148. v := Float64(in.FromValue)
  149. return &v
  150. case "bool":
  151. return Bool(in.FromValue)
  152. case "*bool":
  153. if _, ok := in.FromValue.(*bool); ok {
  154. return in.FromValue
  155. }
  156. v := Bool(in.FromValue)
  157. return &v
  158. case "string":
  159. return String(in.FromValue)
  160. case "*string":
  161. if _, ok := in.FromValue.(*string); ok {
  162. return in.FromValue
  163. }
  164. v := String(in.FromValue)
  165. return &v
  166. case "[]byte":
  167. return Bytes(in.FromValue)
  168. case "[]int":
  169. return Ints(in.FromValue)
  170. case "[]int32":
  171. return Int32s(in.FromValue)
  172. case "[]int64":
  173. return Int64s(in.FromValue)
  174. case "[]uint":
  175. return Uints(in.FromValue)
  176. case "[]uint8":
  177. return Bytes(in.FromValue)
  178. case "[]uint32":
  179. return Uint32s(in.FromValue)
  180. case "[]uint64":
  181. return Uint64s(in.FromValue)
  182. case "[]float32":
  183. return Float32s(in.FromValue)
  184. case "[]float64":
  185. return Float64s(in.FromValue)
  186. case "[]string":
  187. return Strings(in.FromValue)
  188. case "Time", "time.Time":
  189. if len(in.Extra) > 0 {
  190. return Time(in.FromValue, String(in.Extra[0]))
  191. }
  192. return Time(in.FromValue)
  193. case "*time.Time":
  194. var v time.Time
  195. if len(in.Extra) > 0 {
  196. v = Time(in.FromValue, String(in.Extra[0]))
  197. } else {
  198. if _, ok := in.FromValue.(*time.Time); ok {
  199. return in.FromValue
  200. }
  201. v = Time(in.FromValue)
  202. }
  203. return &v
  204. case "GTime", "gtime.Time":
  205. if len(in.Extra) > 0 {
  206. if v := GTime(in.FromValue, String(in.Extra[0])); v != nil {
  207. return *v
  208. } else {
  209. return *gtime.New()
  210. }
  211. }
  212. if v := GTime(in.FromValue); v != nil {
  213. return *v
  214. } else {
  215. return *gtime.New()
  216. }
  217. case "*gtime.Time":
  218. if len(in.Extra) > 0 {
  219. if v := GTime(in.FromValue, String(in.Extra[0])); v != nil {
  220. return v
  221. } else {
  222. return gtime.New()
  223. }
  224. }
  225. if v := GTime(in.FromValue); v != nil {
  226. return v
  227. } else {
  228. return gtime.New()
  229. }
  230. case "Duration", "time.Duration":
  231. return Duration(in.FromValue)
  232. case "*time.Duration":
  233. if _, ok := in.FromValue.(*time.Duration); ok {
  234. return in.FromValue
  235. }
  236. v := Duration(in.FromValue)
  237. return &v
  238. case "map[string]string":
  239. return MapStrStr(in.FromValue)
  240. case "map[string]interface{}":
  241. return Map(in.FromValue)
  242. case "[]map[string]interface{}":
  243. return Maps(in.FromValue)
  244. case "RawMessage", "json.RawMessage":
  245. return Bytes(in.FromValue)
  246. default:
  247. if in.ReferValue != nil {
  248. var referReflectValue reflect.Value
  249. if v, ok := in.ReferValue.(reflect.Value); ok {
  250. referReflectValue = v
  251. } else {
  252. referReflectValue = reflect.ValueOf(in.ReferValue)
  253. }
  254. defer func() {
  255. if recover() != nil {
  256. in.alreadySetToReferValue = false
  257. if err := bindVarToReflectValue(referReflectValue, in.FromValue, nil); err == nil {
  258. in.alreadySetToReferValue = true
  259. convertedValue = referReflectValue.Interface()
  260. }
  261. }
  262. }()
  263. switch referReflectValue.Kind() {
  264. case reflect.Ptr:
  265. // Type converting for custom type pointers.
  266. // Eg:
  267. // type PayMode int
  268. // type Req struct{
  269. // Mode *PayMode
  270. // }
  271. //
  272. // Struct(`{"Mode": 1000}`, &req)
  273. originType := referReflectValue.Type().Elem()
  274. switch originType.Kind() {
  275. case reflect.Struct:
  276. // Not support some kinds.
  277. default:
  278. in.ToTypeName = originType.Kind().String()
  279. in.ReferValue = nil
  280. refElementValue := reflect.ValueOf(doConvert(in))
  281. originTypeValue := reflect.New(refElementValue.Type()).Elem()
  282. originTypeValue.Set(refElementValue)
  283. in.alreadySetToReferValue = true
  284. return originTypeValue.Addr().Convert(referReflectValue.Type()).Interface()
  285. }
  286. case reflect.Map:
  287. var targetValue = reflect.New(referReflectValue.Type()).Elem()
  288. if err := doMapToMap(in.FromValue, targetValue); err == nil {
  289. in.alreadySetToReferValue = true
  290. }
  291. return targetValue.Interface()
  292. }
  293. in.ToTypeName = referReflectValue.Kind().String()
  294. in.ReferValue = nil
  295. in.alreadySetToReferValue = true
  296. convertedValue = reflect.ValueOf(doConvert(in)).Convert(referReflectValue.Type()).Interface()
  297. return convertedValue
  298. }
  299. return in.FromValue
  300. }
  301. }
  302. func doConvertWithReflectValueSet(reflectValue reflect.Value, in doConvertInput) {
  303. convertedValue := doConvert(in)
  304. if !in.alreadySetToReferValue {
  305. reflectValue.Set(reflect.ValueOf(convertedValue))
  306. }
  307. }