gconv_map.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. // Copyright 2018 gf Author(https://github.com/gogf/gf). 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/gerror"
  9. "github.com/gogf/gf/internal/json"
  10. "reflect"
  11. "strings"
  12. "github.com/gogf/gf/internal/empty"
  13. "github.com/gogf/gf/internal/utils"
  14. )
  15. // Map converts any variable <value> to map[string]interface{}. If the parameter <value> is not a
  16. // map/struct/*struct type, then the conversion will fail and returns nil.
  17. //
  18. // If <value> is a struct/*struct object, the second parameter <tags> specifies the most priority
  19. // tags that will be detected, otherwise it detects the tags in order of:
  20. // gconv, json, field name.
  21. func Map(value interface{}, tags ...string) map[string]interface{} {
  22. return doMapConvert(value, false, tags...)
  23. }
  24. // MapDeep does Map function recursively, which means if the attribute of <value>
  25. // is also a struct/*struct, calls Map function on this attribute converting it to
  26. // a map[string]interface{} type variable.
  27. // Also see Map.
  28. func MapDeep(value interface{}, tags ...string) map[string]interface{} {
  29. return doMapConvert(value, true, tags...)
  30. }
  31. // doMapConvert implements the map converting.
  32. // It automatically checks and converts json string to map if <value> is string/[]byte.
  33. //
  34. // TODO completely implement the recursive converting for all types, especially the map.
  35. func doMapConvert(value interface{}, recursive bool, tags ...string) map[string]interface{} {
  36. if value == nil {
  37. return nil
  38. }
  39. newTags := StructTagPriority
  40. switch len(tags) {
  41. case 0:
  42. // No need handle.
  43. case 1:
  44. newTags = append(strings.Split(tags[0], ","), StructTagPriority...)
  45. default:
  46. newTags = append(tags, StructTagPriority...)
  47. }
  48. // Assert the common combination of types, and finally it uses reflection.
  49. dataMap := make(map[string]interface{})
  50. switch r := value.(type) {
  51. case string:
  52. // If it is a JSON string, automatically unmarshal it!
  53. if len(r) > 0 && r[0] == '{' && r[len(r)-1] == '}' {
  54. if err := json.Unmarshal([]byte(r), &dataMap); err != nil {
  55. return nil
  56. }
  57. } else {
  58. return nil
  59. }
  60. case []byte:
  61. // If it is a JSON string, automatically unmarshal it!
  62. if len(r) > 0 && r[0] == '{' && r[len(r)-1] == '}' {
  63. if err := json.Unmarshal(r, &dataMap); err != nil {
  64. return nil
  65. }
  66. } else {
  67. return nil
  68. }
  69. case map[interface{}]interface{}:
  70. for k, v := range r {
  71. dataMap[String(k)] = doMapConvertForMapOrStructValue(false, v, recursive, newTags...)
  72. }
  73. case map[interface{}]string:
  74. for k, v := range r {
  75. dataMap[String(k)] = v
  76. }
  77. case map[interface{}]int:
  78. for k, v := range r {
  79. dataMap[String(k)] = v
  80. }
  81. case map[interface{}]uint:
  82. for k, v := range r {
  83. dataMap[String(k)] = v
  84. }
  85. case map[interface{}]float32:
  86. for k, v := range r {
  87. dataMap[String(k)] = v
  88. }
  89. case map[interface{}]float64:
  90. for k, v := range r {
  91. dataMap[String(k)] = v
  92. }
  93. case map[string]bool:
  94. for k, v := range r {
  95. dataMap[k] = v
  96. }
  97. case map[string]int:
  98. for k, v := range r {
  99. dataMap[k] = v
  100. }
  101. case map[string]uint:
  102. for k, v := range r {
  103. dataMap[k] = v
  104. }
  105. case map[string]float32:
  106. for k, v := range r {
  107. dataMap[k] = v
  108. }
  109. case map[string]float64:
  110. for k, v := range r {
  111. dataMap[k] = v
  112. }
  113. case map[string]interface{}:
  114. if recursive {
  115. // A copy of current map.
  116. for k, v := range r {
  117. dataMap[k] = doMapConvertForMapOrStructValue(false, v, recursive, newTags...)
  118. }
  119. } else {
  120. // It returns the map directly without any changing.
  121. return r
  122. }
  123. case map[int]interface{}:
  124. for k, v := range r {
  125. dataMap[String(k)] = doMapConvertForMapOrStructValue(false, v, recursive, newTags...)
  126. }
  127. case map[int]string:
  128. for k, v := range r {
  129. dataMap[String(k)] = v
  130. }
  131. case map[uint]string:
  132. for k, v := range r {
  133. dataMap[String(k)] = v
  134. }
  135. default:
  136. // Not a common type, it then uses reflection for conversion.
  137. var reflectValue reflect.Value
  138. if v, ok := value.(reflect.Value); ok {
  139. reflectValue = v
  140. } else {
  141. reflectValue = reflect.ValueOf(value)
  142. }
  143. reflectKind := reflectValue.Kind()
  144. // If it is a pointer, we should find its real data type.
  145. for reflectKind == reflect.Ptr {
  146. reflectValue = reflectValue.Elem()
  147. reflectKind = reflectValue.Kind()
  148. }
  149. switch reflectKind {
  150. // If <value> is type of array, it converts the value of even number index as its key and
  151. // the value of odd number index as its corresponding value, for example:
  152. // []string{"k1","v1","k2","v2"} => map[string]interface{}{"k1":"v1", "k2":"v2"}
  153. // []string{"k1","v1","k2"} => map[string]interface{}{"k1":"v1", "k2":nil}
  154. case reflect.Slice, reflect.Array:
  155. length := reflectValue.Len()
  156. for i := 0; i < length; i += 2 {
  157. if i+1 < length {
  158. dataMap[String(reflectValue.Index(i).Interface())] = reflectValue.Index(i + 1).Interface()
  159. } else {
  160. dataMap[String(reflectValue.Index(i).Interface())] = nil
  161. }
  162. }
  163. case reflect.Map, reflect.Struct:
  164. convertedValue := doMapConvertForMapOrStructValue(true, value, recursive, newTags...)
  165. if m, ok := convertedValue.(map[string]interface{}); ok {
  166. return m
  167. }
  168. return nil
  169. default:
  170. return nil
  171. }
  172. }
  173. return dataMap
  174. }
  175. func doMapConvertForMapOrStructValue(isRoot bool, value interface{}, recursive bool, tags ...string) interface{} {
  176. if isRoot == false && recursive == false {
  177. return value
  178. }
  179. var reflectValue reflect.Value
  180. if v, ok := value.(reflect.Value); ok {
  181. reflectValue = v
  182. value = v.Interface()
  183. } else {
  184. reflectValue = reflect.ValueOf(value)
  185. }
  186. reflectKind := reflectValue.Kind()
  187. // If it is a pointer, we should find its real data type.
  188. for reflectKind == reflect.Ptr {
  189. reflectValue = reflectValue.Elem()
  190. reflectKind = reflectValue.Kind()
  191. }
  192. switch reflectKind {
  193. case reflect.Map:
  194. var (
  195. mapKeys = reflectValue.MapKeys()
  196. dataMap = make(map[string]interface{})
  197. )
  198. for _, k := range mapKeys {
  199. dataMap[String(k.Interface())] = doMapConvertForMapOrStructValue(
  200. false,
  201. reflectValue.MapIndex(k).Interface(),
  202. recursive,
  203. tags...,
  204. )
  205. }
  206. if len(dataMap) == 0 {
  207. return value
  208. }
  209. return dataMap
  210. case reflect.Struct:
  211. // Map converting interface check.
  212. if v, ok := value.(apiMapStrAny); ok {
  213. m := v.MapStrAny()
  214. if recursive {
  215. for k, v := range m {
  216. m[k] = doMapConvertForMapOrStructValue(false, v, recursive, tags...)
  217. }
  218. }
  219. return m
  220. }
  221. // Using reflect for converting.
  222. var (
  223. rtField reflect.StructField
  224. rvField reflect.Value
  225. dataMap = make(map[string]interface{}) // result map.
  226. reflectType = reflectValue.Type() // attribute value type.
  227. name = "" // name may be the tag name or the struct attribute name.
  228. )
  229. for i := 0; i < reflectValue.NumField(); i++ {
  230. rtField = reflectType.Field(i)
  231. rvField = reflectValue.Field(i)
  232. // Only convert the public attributes.
  233. fieldName := rtField.Name
  234. if !utils.IsLetterUpper(fieldName[0]) {
  235. continue
  236. }
  237. name = ""
  238. fieldTag := rtField.Tag
  239. for _, tag := range tags {
  240. if name = fieldTag.Get(tag); name != "" {
  241. break
  242. }
  243. }
  244. if name == "" {
  245. name = fieldName
  246. } else {
  247. // Support json tag feature: -, omitempty
  248. name = strings.TrimSpace(name)
  249. if name == "-" {
  250. continue
  251. }
  252. array := strings.Split(name, ",")
  253. if len(array) > 1 {
  254. switch strings.TrimSpace(array[1]) {
  255. case "omitempty":
  256. if empty.IsEmpty(rvField.Interface()) {
  257. continue
  258. } else {
  259. name = strings.TrimSpace(array[0])
  260. }
  261. default:
  262. name = strings.TrimSpace(array[0])
  263. }
  264. }
  265. }
  266. if recursive || rtField.Anonymous {
  267. // Do map converting recursively.
  268. var (
  269. rvAttrField = rvField
  270. rvAttrKind = rvField.Kind()
  271. )
  272. if rvAttrKind == reflect.Ptr {
  273. rvAttrField = rvField.Elem()
  274. rvAttrKind = rvAttrField.Kind()
  275. }
  276. switch rvAttrKind {
  277. case reflect.Struct:
  278. var (
  279. hasNoTag = name == fieldName
  280. rvAttrInterface = rvAttrField.Interface()
  281. )
  282. if hasNoTag && rtField.Anonymous {
  283. // It means this attribute field has no tag.
  284. // Overwrite the attribute with sub-struct attribute fields.
  285. anonymousValue := doMapConvertForMapOrStructValue(false, rvAttrInterface, true, tags...)
  286. if m, ok := anonymousValue.(map[string]interface{}); ok {
  287. for k, v := range m {
  288. dataMap[k] = v
  289. }
  290. } else {
  291. dataMap[name] = rvAttrInterface
  292. }
  293. } else if !hasNoTag && rtField.Anonymous {
  294. // It means this attribute field has desired tag.
  295. dataMap[name] = doMapConvertForMapOrStructValue(false, rvAttrInterface, true, tags...)
  296. } else {
  297. dataMap[name] = doMapConvertForMapOrStructValue(false, rvAttrInterface, false, tags...)
  298. }
  299. // The struct attribute is type of slice.
  300. case reflect.Array, reflect.Slice:
  301. length := rvField.Len()
  302. if length == 0 {
  303. dataMap[name] = rvField.Interface()
  304. break
  305. }
  306. array := make([]interface{}, length)
  307. for i := 0; i < length; i++ {
  308. array[i] = doMapConvertForMapOrStructValue(false, rvField.Index(i), recursive, tags...)
  309. }
  310. dataMap[name] = array
  311. default:
  312. if rvField.IsValid() {
  313. dataMap[name] = reflectValue.Field(i).Interface()
  314. } else {
  315. dataMap[name] = nil
  316. }
  317. }
  318. } else {
  319. // No recursive map value converting
  320. if rvField.IsValid() {
  321. dataMap[name] = reflectValue.Field(i).Interface()
  322. } else {
  323. dataMap[name] = nil
  324. }
  325. }
  326. }
  327. if len(dataMap) == 0 {
  328. return value
  329. }
  330. return dataMap
  331. // The given value is type of slice.
  332. case reflect.Array, reflect.Slice:
  333. length := reflectValue.Len()
  334. if length == 0 {
  335. break
  336. }
  337. array := make([]interface{}, reflectValue.Len())
  338. for i := 0; i < length; i++ {
  339. array[i] = doMapConvertForMapOrStructValue(false, reflectValue.Index(i), recursive, tags...)
  340. }
  341. return array
  342. }
  343. return value
  344. }
  345. // MapStrStr converts <value> to map[string]string.
  346. // Note that there might be data copy for this map type converting.
  347. func MapStrStr(value interface{}, tags ...string) map[string]string {
  348. if r, ok := value.(map[string]string); ok {
  349. return r
  350. }
  351. m := Map(value, tags...)
  352. if len(m) > 0 {
  353. vMap := make(map[string]string, len(m))
  354. for k, v := range m {
  355. vMap[k] = String(v)
  356. }
  357. return vMap
  358. }
  359. return nil
  360. }
  361. // MapStrStrDeep converts <value> to map[string]string recursively.
  362. // Note that there might be data copy for this map type converting.
  363. func MapStrStrDeep(value interface{}, tags ...string) map[string]string {
  364. if r, ok := value.(map[string]string); ok {
  365. return r
  366. }
  367. m := MapDeep(value, tags...)
  368. if len(m) > 0 {
  369. vMap := make(map[string]string, len(m))
  370. for k, v := range m {
  371. vMap[k] = String(v)
  372. }
  373. return vMap
  374. }
  375. return nil
  376. }
  377. // MapToMap converts any map type variable <params> to another map type variable <pointer>
  378. // using reflect.
  379. // See doMapToMap.
  380. func MapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) error {
  381. return doMapToMap(params, pointer, mapping...)
  382. }
  383. // MapToMapDeep converts any map type variable <params> to another map type variable <pointer>
  384. // using reflect recursively.
  385. // Deprecated, use MapToMap instead.
  386. func MapToMapDeep(params interface{}, pointer interface{}, mapping ...map[string]string) error {
  387. return doMapToMap(params, pointer, mapping...)
  388. }
  389. // doMapToMap converts any map type variable <params> to another map type variable <pointer>.
  390. //
  391. // The parameter <params> can be any type of map, like:
  392. // map[string]string, map[string]struct, , map[string]*struct, etc.
  393. //
  394. // The parameter <pointer> should be type of *map, like:
  395. // map[int]string, map[string]struct, , map[string]*struct, etc.
  396. //
  397. // The optional parameter <mapping> is used for struct attribute to map key mapping, which makes
  398. // sense only if the items of original map <params> is type struct.
  399. func doMapToMap(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
  400. var (
  401. paramsRv = reflect.ValueOf(params)
  402. paramsKind = paramsRv.Kind()
  403. )
  404. if paramsKind == reflect.Ptr {
  405. paramsRv = paramsRv.Elem()
  406. paramsKind = paramsRv.Kind()
  407. }
  408. if paramsKind != reflect.Map {
  409. return gerror.New("params should be type of map")
  410. }
  411. // Empty params map, no need continue.
  412. if paramsRv.Len() == 0 {
  413. return nil
  414. }
  415. var pointerRv reflect.Value
  416. if v, ok := pointer.(reflect.Value); ok {
  417. pointerRv = v
  418. } else {
  419. pointerRv = reflect.ValueOf(pointer)
  420. }
  421. pointerKind := pointerRv.Kind()
  422. for pointerKind == reflect.Ptr {
  423. pointerRv = pointerRv.Elem()
  424. pointerKind = pointerRv.Kind()
  425. }
  426. if pointerKind != reflect.Map {
  427. return gerror.New("pointer should be type of *map")
  428. }
  429. defer func() {
  430. // Catch the panic, especially the reflect operation panics.
  431. if exception := recover(); exception != nil {
  432. if e, ok := exception.(errorStack); ok {
  433. err = e
  434. } else {
  435. err = gerror.NewSkipf(1, "%v", exception)
  436. }
  437. }
  438. }()
  439. var (
  440. paramsKeys = paramsRv.MapKeys()
  441. pointerKeyType = pointerRv.Type().Key()
  442. pointerValueType = pointerRv.Type().Elem()
  443. pointerValueKind = pointerValueType.Kind()
  444. dataMap = reflect.MakeMapWithSize(pointerRv.Type(), len(paramsKeys))
  445. )
  446. // Retrieve the true element type of target map.
  447. if pointerValueKind == reflect.Ptr {
  448. pointerValueKind = pointerValueType.Elem().Kind()
  449. }
  450. for _, key := range paramsKeys {
  451. e := reflect.New(pointerValueType).Elem()
  452. switch pointerValueKind {
  453. case reflect.Map, reflect.Struct:
  454. if err = Struct(paramsRv.MapIndex(key).Interface(), e, mapping...); err != nil {
  455. return err
  456. }
  457. default:
  458. e.Set(
  459. reflect.ValueOf(
  460. Convert(
  461. paramsRv.MapIndex(key).Interface(),
  462. pointerValueType.String(),
  463. ),
  464. ),
  465. )
  466. }
  467. dataMap.SetMapIndex(
  468. reflect.ValueOf(
  469. Convert(
  470. key.Interface(),
  471. pointerKeyType.Name(),
  472. ),
  473. ),
  474. e,
  475. )
  476. }
  477. pointerRv.Set(dataMap)
  478. return nil
  479. }
  480. // MapToMaps converts any map type variable <params> to another map type variable <pointer>.
  481. // See doMapToMaps.
  482. func MapToMaps(params interface{}, pointer interface{}, mapping ...map[string]string) error {
  483. return doMapToMaps(params, pointer, mapping...)
  484. }
  485. // MapToMapsDeep converts any map type variable <params> to another map type variable
  486. // <pointer> recursively.
  487. // Deprecated, use MapToMaps instead.
  488. func MapToMapsDeep(params interface{}, pointer interface{}, mapping ...map[string]string) error {
  489. return doMapToMaps(params, pointer, mapping...)
  490. }
  491. // doMapToMaps converts any map type variable <params> to another map type variable <pointer>.
  492. //
  493. // The parameter <params> can be any type of map, of which the item type is slice map, like:
  494. // map[int][]map, map[string][]map.
  495. //
  496. // The parameter <pointer> should be type of *map, of which the item type is slice map, like:
  497. // map[string][]struct, map[string][]*struct.
  498. //
  499. // The optional parameter <mapping> is used for struct attribute to map key mapping, which makes
  500. // sense only if the items of original map is type struct.
  501. //
  502. // TODO it's supposed supporting target type <pointer> like: map[int][]map, map[string][]map.
  503. func doMapToMaps(params interface{}, pointer interface{}, mapping ...map[string]string) (err error) {
  504. var (
  505. paramsRv = reflect.ValueOf(params)
  506. paramsKind = paramsRv.Kind()
  507. )
  508. if paramsKind == reflect.Ptr {
  509. paramsRv = paramsRv.Elem()
  510. paramsKind = paramsRv.Kind()
  511. }
  512. if paramsKind != reflect.Map {
  513. return gerror.New("params should be type of map")
  514. }
  515. // Empty params map, no need continue.
  516. if paramsRv.Len() == 0 {
  517. return nil
  518. }
  519. var (
  520. pointerRv = reflect.ValueOf(pointer)
  521. pointerKind = pointerRv.Kind()
  522. )
  523. for pointerKind == reflect.Ptr {
  524. pointerRv = pointerRv.Elem()
  525. pointerKind = pointerRv.Kind()
  526. }
  527. if pointerKind != reflect.Map {
  528. return gerror.New("pointer should be type of *map/**map")
  529. }
  530. defer func() {
  531. // Catch the panic, especially the reflect operation panics.
  532. if exception := recover(); exception != nil {
  533. if e, ok := exception.(errorStack); ok {
  534. err = e
  535. } else {
  536. err = gerror.NewSkipf(1, "%v", exception)
  537. }
  538. }
  539. }()
  540. var (
  541. paramsKeys = paramsRv.MapKeys()
  542. pointerKeyType = pointerRv.Type().Key()
  543. pointerValueType = pointerRv.Type().Elem()
  544. dataMap = reflect.MakeMapWithSize(pointerRv.Type(), len(paramsKeys))
  545. )
  546. for _, key := range paramsKeys {
  547. e := reflect.New(pointerValueType).Elem()
  548. if err = Structs(paramsRv.MapIndex(key).Interface(), e.Addr(), mapping...); err != nil {
  549. return err
  550. }
  551. dataMap.SetMapIndex(
  552. reflect.ValueOf(
  553. Convert(
  554. key.Interface(),
  555. pointerKeyType.Name(),
  556. ),
  557. ),
  558. e,
  559. )
  560. }
  561. pointerRv.Set(dataMap)
  562. return nil
  563. }