gconv_map.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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. "github.com/gogf/gf/internal/json"
  9. "reflect"
  10. "strings"
  11. "github.com/gogf/gf/internal/empty"
  12. "github.com/gogf/gf/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]interface{}:
  113. if recursive {
  114. // A copy of current map.
  115. for k, v := range r {
  116. dataMap[k] = doMapConvertForMapOrStructValue(false, v, recursive, newTags...)
  117. }
  118. } else {
  119. // It returns the map directly without any changing.
  120. return r
  121. }
  122. case map[int]interface{}:
  123. for k, v := range r {
  124. dataMap[String(k)] = doMapConvertForMapOrStructValue(false, v, recursive, newTags...)
  125. }
  126. case map[int]string:
  127. for k, v := range r {
  128. dataMap[String(k)] = v
  129. }
  130. case map[uint]string:
  131. for k, v := range r {
  132. dataMap[String(k)] = v
  133. }
  134. default:
  135. // Not a common type, it then uses reflection for conversion.
  136. var reflectValue reflect.Value
  137. if v, ok := value.(reflect.Value); ok {
  138. reflectValue = v
  139. } else {
  140. reflectValue = reflect.ValueOf(value)
  141. }
  142. reflectKind := reflectValue.Kind()
  143. // If it is a pointer, we should find its real data type.
  144. for reflectKind == reflect.Ptr {
  145. reflectValue = reflectValue.Elem()
  146. reflectKind = reflectValue.Kind()
  147. }
  148. switch reflectKind {
  149. // If `value` is type of array, it converts the value of even number index as its key and
  150. // the value of odd number index as its corresponding value, for example:
  151. // []string{"k1","v1","k2","v2"} => map[string]interface{}{"k1":"v1", "k2":"v2"}
  152. // []string{"k1","v1","k2"} => map[string]interface{}{"k1":"v1", "k2":nil}
  153. case reflect.Slice, reflect.Array:
  154. length := reflectValue.Len()
  155. for i := 0; i < length; i += 2 {
  156. if i+1 < length {
  157. dataMap[String(reflectValue.Index(i).Interface())] = reflectValue.Index(i + 1).Interface()
  158. } else {
  159. dataMap[String(reflectValue.Index(i).Interface())] = nil
  160. }
  161. }
  162. case reflect.Map, reflect.Struct, reflect.Interface:
  163. convertedValue := doMapConvertForMapOrStructValue(true, value, recursive, newTags...)
  164. if m, ok := convertedValue.(map[string]interface{}); ok {
  165. return m
  166. }
  167. return nil
  168. default:
  169. return nil
  170. }
  171. }
  172. return dataMap
  173. }
  174. func doMapConvertForMapOrStructValue(isRoot bool, value interface{}, recursive bool, tags ...string) interface{} {
  175. if isRoot == false && recursive == false {
  176. return value
  177. }
  178. var reflectValue reflect.Value
  179. if v, ok := value.(reflect.Value); ok {
  180. reflectValue = v
  181. value = v.Interface()
  182. } else {
  183. reflectValue = reflect.ValueOf(value)
  184. }
  185. reflectKind := reflectValue.Kind()
  186. // If it is a pointer, we should find its real data type.
  187. for reflectKind == reflect.Ptr {
  188. reflectValue = reflectValue.Elem()
  189. reflectKind = reflectValue.Kind()
  190. }
  191. switch reflectKind {
  192. case reflect.Map:
  193. var (
  194. mapKeys = reflectValue.MapKeys()
  195. dataMap = make(map[string]interface{})
  196. )
  197. for _, k := range mapKeys {
  198. dataMap[String(k.Interface())] = doMapConvertForMapOrStructValue(
  199. false,
  200. reflectValue.MapIndex(k).Interface(),
  201. recursive,
  202. tags...,
  203. )
  204. }
  205. if len(dataMap) == 0 {
  206. return value
  207. }
  208. return dataMap
  209. case reflect.Struct:
  210. // Map converting interface check.
  211. if v, ok := value.(apiMapStrAny); ok {
  212. m := v.MapStrAny()
  213. if recursive {
  214. for k, v := range m {
  215. m[k] = doMapConvertForMapOrStructValue(false, v, recursive, tags...)
  216. }
  217. }
  218. return m
  219. }
  220. // Using reflect for converting.
  221. var (
  222. rtField reflect.StructField
  223. rvField reflect.Value
  224. dataMap = make(map[string]interface{}) // result map.
  225. reflectType = reflectValue.Type() // attribute value type.
  226. mapKey = "" // mapKey may be the tag name or the struct attribute name.
  227. )
  228. for i := 0; i < reflectValue.NumField(); i++ {
  229. rtField = reflectType.Field(i)
  230. rvField = reflectValue.Field(i)
  231. // Only convert the public attributes.
  232. fieldName := rtField.Name
  233. if !utils.IsLetterUpper(fieldName[0]) {
  234. continue
  235. }
  236. mapKey = ""
  237. fieldTag := rtField.Tag
  238. for _, tag := range tags {
  239. if mapKey = fieldTag.Get(tag); mapKey != "" {
  240. break
  241. }
  242. }
  243. if mapKey == "" {
  244. mapKey = fieldName
  245. } else {
  246. // Support json tag feature: -, omitempty
  247. mapKey = strings.TrimSpace(mapKey)
  248. if mapKey == "-" {
  249. continue
  250. }
  251. array := strings.Split(mapKey, ",")
  252. if len(array) > 1 {
  253. switch strings.TrimSpace(array[1]) {
  254. case "omitempty":
  255. if empty.IsEmpty(rvField.Interface()) {
  256. continue
  257. } else {
  258. mapKey = strings.TrimSpace(array[0])
  259. }
  260. default:
  261. mapKey = strings.TrimSpace(array[0])
  262. }
  263. }
  264. }
  265. if recursive || rtField.Anonymous {
  266. // Do map converting recursively.
  267. var (
  268. rvAttrField = rvField
  269. rvAttrKind = rvField.Kind()
  270. )
  271. if rvAttrKind == reflect.Ptr {
  272. rvAttrField = rvField.Elem()
  273. rvAttrKind = rvAttrField.Kind()
  274. }
  275. switch rvAttrKind {
  276. case reflect.Struct:
  277. var (
  278. hasNoTag = mapKey == fieldName
  279. rvAttrInterface = rvAttrField.Interface()
  280. )
  281. if hasNoTag && rtField.Anonymous {
  282. // It means this attribute field has no tag.
  283. // Overwrite the attribute with sub-struct attribute fields.
  284. anonymousValue := doMapConvertForMapOrStructValue(false, rvAttrInterface, true, tags...)
  285. if m, ok := anonymousValue.(map[string]interface{}); ok {
  286. for k, v := range m {
  287. dataMap[k] = v
  288. }
  289. } else {
  290. dataMap[mapKey] = rvAttrInterface
  291. }
  292. } else if !hasNoTag && rtField.Anonymous {
  293. // It means this attribute field has desired tag.
  294. dataMap[mapKey] = doMapConvertForMapOrStructValue(false, rvAttrInterface, true, tags...)
  295. } else {
  296. dataMap[mapKey] = doMapConvertForMapOrStructValue(false, rvAttrInterface, recursive, tags...)
  297. }
  298. // The struct attribute is type of slice.
  299. case reflect.Array, reflect.Slice:
  300. length := rvField.Len()
  301. if length == 0 {
  302. dataMap[mapKey] = rvField.Interface()
  303. break
  304. }
  305. array := make([]interface{}, length)
  306. for i := 0; i < length; i++ {
  307. array[i] = doMapConvertForMapOrStructValue(false, rvField.Index(i), recursive, tags...)
  308. }
  309. dataMap[mapKey] = array
  310. default:
  311. if rvField.IsValid() {
  312. dataMap[mapKey] = reflectValue.Field(i).Interface()
  313. } else {
  314. dataMap[mapKey] = nil
  315. }
  316. }
  317. } else {
  318. // No recursive map value converting
  319. if rvField.IsValid() {
  320. dataMap[mapKey] = reflectValue.Field(i).Interface()
  321. } else {
  322. dataMap[mapKey] = nil
  323. }
  324. }
  325. }
  326. if len(dataMap) == 0 {
  327. return value
  328. }
  329. return dataMap
  330. // The given value is type of slice.
  331. case reflect.Array, reflect.Slice:
  332. length := reflectValue.Len()
  333. if length == 0 {
  334. break
  335. }
  336. array := make([]interface{}, reflectValue.Len())
  337. for i := 0; i < length; i++ {
  338. array[i] = doMapConvertForMapOrStructValue(false, reflectValue.Index(i), recursive, tags...)
  339. }
  340. return array
  341. }
  342. return value
  343. }
  344. // MapStrStr converts `value` to map[string]string.
  345. // Note that there might be data copy for this map type converting.
  346. func MapStrStr(value interface{}, tags ...string) map[string]string {
  347. if r, ok := value.(map[string]string); ok {
  348. return r
  349. }
  350. m := Map(value, tags...)
  351. if len(m) > 0 {
  352. vMap := make(map[string]string, len(m))
  353. for k, v := range m {
  354. vMap[k] = String(v)
  355. }
  356. return vMap
  357. }
  358. return nil
  359. }
  360. // MapStrStrDeep converts `value` to map[string]string recursively.
  361. // Note that there might be data copy for this map type converting.
  362. func MapStrStrDeep(value interface{}, tags ...string) map[string]string {
  363. if r, ok := value.(map[string]string); ok {
  364. return r
  365. }
  366. m := MapDeep(value, tags...)
  367. if len(m) > 0 {
  368. vMap := make(map[string]string, len(m))
  369. for k, v := range m {
  370. vMap[k] = String(v)
  371. }
  372. return vMap
  373. }
  374. return nil
  375. }