gconv_map.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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. "strings"
  10. "github.com/gogf/gf/v2/internal/empty"
  11. "github.com/gogf/gf/v2/internal/json"
  12. "github.com/gogf/gf/v2/internal/utils"
  13. )
  14. // Map converts any variable `value` to map[string]interface{}. If the parameter `value` is not a
  15. // map/struct/*struct type, then the conversion will fail and returns nil.
  16. //
  17. // If `value` is a struct/*struct object, the second parameter `tags` specifies the most priority
  18. // tags that will be detected, otherwise it detects the tags in order of:
  19. // gconv, json, field name.
  20. func Map(value interface{}, tags ...string) map[string]interface{} {
  21. return doMapConvert(value, false, tags...)
  22. }
  23. // MapDeep does Map function recursively, which means if the attribute of `value`
  24. // is also a struct/*struct, calls Map function on this attribute converting it to
  25. // a map[string]interface{} type variable.
  26. // Also see Map.
  27. func MapDeep(value interface{}, tags ...string) map[string]interface{} {
  28. return doMapConvert(value, true, tags...)
  29. }
  30. // doMapConvert implements the map converting.
  31. // It automatically checks and converts json string to map if `value` is string/[]byte.
  32. //
  33. // TODO completely implement the recursive converting for all types, especially the map.
  34. func doMapConvert(value interface{}, recursive bool, tags ...string) map[string]interface{} {
  35. if value == nil {
  36. return nil
  37. }
  38. newTags := StructTagPriority
  39. switch len(tags) {
  40. case 0:
  41. // No need handling.
  42. case 1:
  43. newTags = append(strings.Split(tags[0], ","), StructTagPriority...)
  44. default:
  45. newTags = append(tags, StructTagPriority...)
  46. }
  47. // Assert the common combination of types, and finally it uses reflection.
  48. dataMap := make(map[string]interface{})
  49. switch r := value.(type) {
  50. case string:
  51. // If it is a JSON string, automatically unmarshal it!
  52. if len(r) > 0 && r[0] == '{' && r[len(r)-1] == '}' {
  53. if err := json.UnmarshalUseNumber([]byte(r), &dataMap); err != nil {
  54. return nil
  55. }
  56. } else {
  57. return nil
  58. }
  59. case []byte:
  60. // If it is a JSON string, automatically unmarshal it!
  61. if len(r) > 0 && r[0] == '{' && r[len(r)-1] == '}' {
  62. if err := json.UnmarshalUseNumber(r, &dataMap); err != nil {
  63. return nil
  64. }
  65. } else {
  66. return nil
  67. }
  68. case map[interface{}]interface{}:
  69. for k, v := range r {
  70. dataMap[String(k)] = doMapConvertForMapOrStructValue(false, v, recursive, newTags...)
  71. }
  72. case map[interface{}]string:
  73. for k, v := range r {
  74. dataMap[String(k)] = v
  75. }
  76. case map[interface{}]int:
  77. for k, v := range r {
  78. dataMap[String(k)] = v
  79. }
  80. case map[interface{}]uint:
  81. for k, v := range r {
  82. dataMap[String(k)] = v
  83. }
  84. case map[interface{}]float32:
  85. for k, v := range r {
  86. dataMap[String(k)] = v
  87. }
  88. case map[interface{}]float64:
  89. for k, v := range r {
  90. dataMap[String(k)] = v
  91. }
  92. case map[string]bool:
  93. for k, v := range r {
  94. dataMap[k] = v
  95. }
  96. case map[string]int:
  97. for k, v := range r {
  98. dataMap[k] = v
  99. }
  100. case map[string]uint:
  101. for k, v := range r {
  102. dataMap[k] = v
  103. }
  104. case map[string]float32:
  105. for k, v := range r {
  106. dataMap[k] = v
  107. }
  108. case map[string]float64:
  109. for k, v := range r {
  110. dataMap[k] = v
  111. }
  112. case map[string]string:
  113. for k, v := range r {
  114. dataMap[k] = v
  115. }
  116. case map[string]interface{}:
  117. if recursive {
  118. // A copy of current map.
  119. for k, v := range r {
  120. dataMap[k] = doMapConvertForMapOrStructValue(false, v, recursive, newTags...)
  121. }
  122. } else {
  123. // It returns the map directly without any changing.
  124. return r
  125. }
  126. case map[int]interface{}:
  127. for k, v := range r {
  128. dataMap[String(k)] = doMapConvertForMapOrStructValue(false, v, recursive, newTags...)
  129. }
  130. case map[int]string:
  131. for k, v := range r {
  132. dataMap[String(k)] = v
  133. }
  134. case map[uint]string:
  135. for k, v := range r {
  136. dataMap[String(k)] = v
  137. }
  138. default:
  139. // Not a common type, it then uses reflection for conversion.
  140. var reflectValue reflect.Value
  141. if v, ok := value.(reflect.Value); ok {
  142. reflectValue = v
  143. } else {
  144. reflectValue = reflect.ValueOf(value)
  145. }
  146. reflectKind := reflectValue.Kind()
  147. // If it is a pointer, we should find its real data type.
  148. for reflectKind == reflect.Ptr {
  149. reflectValue = reflectValue.Elem()
  150. reflectKind = reflectValue.Kind()
  151. }
  152. switch reflectKind {
  153. // If `value` is type of array, it converts the value of even number index as its key and
  154. // the value of odd number index as its corresponding value, for example:
  155. // []string{"k1","v1","k2","v2"} => map[string]interface{}{"k1":"v1", "k2":"v2"}
  156. // []string{"k1","v1","k2"} => map[string]interface{}{"k1":"v1", "k2":nil}
  157. case reflect.Slice, reflect.Array:
  158. length := reflectValue.Len()
  159. for i := 0; i < length; i += 2 {
  160. if i+1 < length {
  161. dataMap[String(reflectValue.Index(i).Interface())] = reflectValue.Index(i + 1).Interface()
  162. } else {
  163. dataMap[String(reflectValue.Index(i).Interface())] = nil
  164. }
  165. }
  166. case reflect.Map, reflect.Struct, reflect.Interface:
  167. convertedValue := doMapConvertForMapOrStructValue(true, value, recursive, newTags...)
  168. if m, ok := convertedValue.(map[string]interface{}); ok {
  169. return m
  170. }
  171. return nil
  172. default:
  173. return nil
  174. }
  175. }
  176. return dataMap
  177. }
  178. func doMapConvertForMapOrStructValue(isRoot bool, value interface{}, recursive bool, tags ...string) interface{} {
  179. if isRoot == false && recursive == false {
  180. return value
  181. }
  182. var reflectValue reflect.Value
  183. if v, ok := value.(reflect.Value); ok {
  184. reflectValue = v
  185. value = v.Interface()
  186. } else {
  187. reflectValue = reflect.ValueOf(value)
  188. }
  189. reflectKind := reflectValue.Kind()
  190. // If it is a pointer, we should find its real data type.
  191. for reflectKind == reflect.Ptr {
  192. reflectValue = reflectValue.Elem()
  193. reflectKind = reflectValue.Kind()
  194. }
  195. switch reflectKind {
  196. case reflect.Map:
  197. var (
  198. mapKeys = reflectValue.MapKeys()
  199. dataMap = make(map[string]interface{})
  200. )
  201. for _, k := range mapKeys {
  202. dataMap[String(k.Interface())] = doMapConvertForMapOrStructValue(
  203. false,
  204. reflectValue.MapIndex(k).Interface(),
  205. recursive,
  206. tags...,
  207. )
  208. }
  209. return dataMap
  210. case reflect.Struct:
  211. var dataMap = make(map[string]interface{})
  212. // Map converting interface check.
  213. if v, ok := value.(iMapStrAny); ok {
  214. // Value copy, in case of concurrent safety.
  215. for mapK, mapV := range v.MapStrAny() {
  216. if recursive {
  217. dataMap[mapK] = doMapConvertForMapOrStructValue(false, mapV, recursive, tags...)
  218. } else {
  219. dataMap[mapK] = mapV
  220. }
  221. }
  222. return dataMap
  223. }
  224. // Using reflect for converting.
  225. var (
  226. rtField reflect.StructField
  227. rvField reflect.Value
  228. reflectType = reflectValue.Type() // attribute value type.
  229. mapKey = "" // mapKey may be the tag name or the struct attribute name.
  230. )
  231. for i := 0; i < reflectValue.NumField(); i++ {
  232. rtField = reflectType.Field(i)
  233. rvField = reflectValue.Field(i)
  234. // Only convert the public attributes.
  235. fieldName := rtField.Name
  236. if !utils.IsLetterUpper(fieldName[0]) {
  237. continue
  238. }
  239. mapKey = ""
  240. fieldTag := rtField.Tag
  241. for _, tag := range tags {
  242. if mapKey = fieldTag.Get(tag); mapKey != "" {
  243. break
  244. }
  245. }
  246. if mapKey == "" {
  247. mapKey = fieldName
  248. } else {
  249. // Support json tag feature: -, omitempty
  250. mapKey = strings.TrimSpace(mapKey)
  251. if mapKey == "-" {
  252. continue
  253. }
  254. array := strings.Split(mapKey, ",")
  255. if len(array) > 1 {
  256. switch strings.TrimSpace(array[1]) {
  257. case "omitempty":
  258. if empty.IsEmpty(rvField.Interface()) {
  259. continue
  260. } else {
  261. mapKey = strings.TrimSpace(array[0])
  262. }
  263. default:
  264. mapKey = strings.TrimSpace(array[0])
  265. }
  266. }
  267. }
  268. if recursive || rtField.Anonymous {
  269. // Do map converting recursively.
  270. var (
  271. rvAttrField = rvField
  272. rvAttrKind = rvField.Kind()
  273. )
  274. if rvAttrKind == reflect.Ptr {
  275. rvAttrField = rvField.Elem()
  276. rvAttrKind = rvAttrField.Kind()
  277. }
  278. switch rvAttrKind {
  279. case reflect.Struct:
  280. // Embedded struct and has no fields, just ignores it.
  281. // Eg: gmeta.Meta
  282. if rvAttrField.Type().NumField() == 0 {
  283. continue
  284. }
  285. var (
  286. hasNoTag = mapKey == fieldName
  287. rvAttrInterface = rvAttrField.Interface()
  288. )
  289. if hasNoTag && rtField.Anonymous {
  290. // It means this attribute field has no tag.
  291. // Overwrite the attribute with sub-struct attribute fields.
  292. anonymousValue := doMapConvertForMapOrStructValue(false, rvAttrInterface, true, tags...)
  293. if m, ok := anonymousValue.(map[string]interface{}); ok {
  294. for k, v := range m {
  295. dataMap[k] = v
  296. }
  297. } else {
  298. dataMap[mapKey] = rvAttrInterface
  299. }
  300. } else if !hasNoTag && rtField.Anonymous {
  301. // It means this attribute field has desired tag.
  302. dataMap[mapKey] = doMapConvertForMapOrStructValue(false, rvAttrInterface, true, tags...)
  303. } else {
  304. dataMap[mapKey] = doMapConvertForMapOrStructValue(false, rvAttrInterface, recursive, tags...)
  305. }
  306. // The struct attribute is type of slice.
  307. case reflect.Array, reflect.Slice:
  308. length := rvAttrField.Len()
  309. if length == 0 {
  310. dataMap[mapKey] = rvAttrField.Interface()
  311. break
  312. }
  313. array := make([]interface{}, length)
  314. for arrayIndex := 0; arrayIndex < length; arrayIndex++ {
  315. array[arrayIndex] = doMapConvertForMapOrStructValue(
  316. false, rvAttrField.Index(arrayIndex), recursive, tags...,
  317. )
  318. }
  319. dataMap[mapKey] = array
  320. case reflect.Map:
  321. var (
  322. mapKeys = rvAttrField.MapKeys()
  323. nestedMap = make(map[string]interface{})
  324. )
  325. for _, k := range mapKeys {
  326. nestedMap[String(k.Interface())] = doMapConvertForMapOrStructValue(
  327. false,
  328. rvAttrField.MapIndex(k).Interface(),
  329. recursive,
  330. tags...,
  331. )
  332. }
  333. dataMap[mapKey] = nestedMap
  334. default:
  335. if rvField.IsValid() {
  336. dataMap[mapKey] = reflectValue.Field(i).Interface()
  337. } else {
  338. dataMap[mapKey] = nil
  339. }
  340. }
  341. } else {
  342. // No recursive map value converting
  343. if rvField.IsValid() {
  344. dataMap[mapKey] = reflectValue.Field(i).Interface()
  345. } else {
  346. dataMap[mapKey] = nil
  347. }
  348. }
  349. }
  350. if len(dataMap) == 0 {
  351. return value
  352. }
  353. return dataMap
  354. // The given value is type of slice.
  355. case reflect.Array, reflect.Slice:
  356. length := reflectValue.Len()
  357. if length == 0 {
  358. break
  359. }
  360. array := make([]interface{}, reflectValue.Len())
  361. for i := 0; i < length; i++ {
  362. array[i] = doMapConvertForMapOrStructValue(false, reflectValue.Index(i), recursive, tags...)
  363. }
  364. return array
  365. }
  366. return value
  367. }
  368. // MapStrStr converts `value` to map[string]string.
  369. // Note that there might be data copy for this map type converting.
  370. func MapStrStr(value interface{}, tags ...string) map[string]string {
  371. if r, ok := value.(map[string]string); ok {
  372. return r
  373. }
  374. m := Map(value, tags...)
  375. if len(m) > 0 {
  376. vMap := make(map[string]string, len(m))
  377. for k, v := range m {
  378. vMap[k] = String(v)
  379. }
  380. return vMap
  381. }
  382. return nil
  383. }
  384. // MapStrStrDeep converts `value` to map[string]string recursively.
  385. // Note that there might be data copy for this map type converting.
  386. func MapStrStrDeep(value interface{}, tags ...string) map[string]string {
  387. if r, ok := value.(map[string]string); ok {
  388. return r
  389. }
  390. m := MapDeep(value, tags...)
  391. if len(m) > 0 {
  392. vMap := make(map[string]string, len(m))
  393. for k, v := range m {
  394. vMap[k] = String(v)
  395. }
  396. return vMap
  397. }
  398. return nil
  399. }