github.com/gogf/gf/v2@v2.7.4/util/gconv/gconv_maptomaps.go (about) 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 7 package gconv 8 9 import ( 10 "reflect" 11 12 "github.com/gogf/gf/v2/errors/gcode" 13 "github.com/gogf/gf/v2/errors/gerror" 14 ) 15 16 // MapToMaps converts any slice type variable `params` to another map slice type variable `pointer`. 17 // See doMapToMaps. 18 func MapToMaps(params interface{}, pointer interface{}, mapping ...map[string]string) error { 19 return Scan(params, pointer, mapping...) 20 } 21 22 // doMapToMaps converts any map type variable `params` to another map slice variable `pointer`. 23 // 24 // The parameter `params` can be type of []map, []*map, []struct, []*struct. 25 // 26 // The parameter `pointer` should be type of []map, []*map. 27 // 28 // The optional parameter `mapping` is used for struct attribute to map key mapping, which makes 29 // sense only if the item of `params` is type struct. 30 func doMapToMaps(params interface{}, pointer interface{}, paramKeyToAttrMap ...map[string]string) (err error) { 31 // Params and its element type check. 32 var ( 33 paramsRv reflect.Value 34 paramsKind reflect.Kind 35 ) 36 if v, ok := params.(reflect.Value); ok { 37 paramsRv = v 38 } else { 39 paramsRv = reflect.ValueOf(params) 40 } 41 paramsKind = paramsRv.Kind() 42 if paramsKind == reflect.Ptr { 43 paramsRv = paramsRv.Elem() 44 paramsKind = paramsRv.Kind() 45 } 46 if paramsKind != reflect.Array && paramsKind != reflect.Slice { 47 return gerror.NewCode( 48 gcode.CodeInvalidParameter, 49 "params should be type of slice, example: []map/[]*map/[]struct/[]*struct", 50 ) 51 } 52 var ( 53 paramsElem = paramsRv.Type().Elem() 54 paramsElemKind = paramsElem.Kind() 55 ) 56 if paramsElemKind == reflect.Ptr { 57 paramsElem = paramsElem.Elem() 58 paramsElemKind = paramsElem.Kind() 59 } 60 if paramsElemKind != reflect.Map && 61 paramsElemKind != reflect.Struct && 62 paramsElemKind != reflect.Interface { 63 return gerror.NewCodef( 64 gcode.CodeInvalidParameter, 65 "params element should be type of map/*map/struct/*struct, but got: %s", 66 paramsElemKind, 67 ) 68 } 69 // Empty slice, no need continue. 70 if paramsRv.Len() == 0 { 71 return nil 72 } 73 // Pointer and its element type check. 74 var ( 75 pointerRv = reflect.ValueOf(pointer) 76 pointerKind = pointerRv.Kind() 77 ) 78 for pointerKind == reflect.Ptr { 79 pointerRv = pointerRv.Elem() 80 pointerKind = pointerRv.Kind() 81 } 82 if pointerKind != reflect.Array && pointerKind != reflect.Slice { 83 return gerror.NewCode(gcode.CodeInvalidParameter, "pointer should be type of *[]map/*[]*map") 84 } 85 var ( 86 pointerElemType = pointerRv.Type().Elem() 87 pointerElemKind = pointerElemType.Kind() 88 ) 89 if pointerElemKind == reflect.Ptr { 90 pointerElemKind = pointerElemType.Elem().Kind() 91 } 92 if pointerElemKind != reflect.Map { 93 return gerror.NewCode(gcode.CodeInvalidParameter, "pointer element should be type of map/*map") 94 } 95 defer func() { 96 // Catch the panic, especially the reflection operation panics. 97 if exception := recover(); exception != nil { 98 if v, ok := exception.(error); ok && gerror.HasStack(v) { 99 err = v 100 } else { 101 err = gerror.NewCodeSkipf(gcode.CodeInternalPanic, 1, "%+v", exception) 102 } 103 } 104 }() 105 var ( 106 pointerSlice = reflect.MakeSlice(pointerRv.Type(), paramsRv.Len(), paramsRv.Len()) 107 ) 108 for i := 0; i < paramsRv.Len(); i++ { 109 var item reflect.Value 110 if pointerElemType.Kind() == reflect.Ptr { 111 item = reflect.New(pointerElemType.Elem()) 112 if err = MapToMap(paramsRv.Index(i).Interface(), item, paramKeyToAttrMap...); err != nil { 113 return err 114 } 115 pointerSlice.Index(i).Set(item) 116 } else { 117 item = reflect.New(pointerElemType) 118 if err = MapToMap(paramsRv.Index(i).Interface(), item, paramKeyToAttrMap...); err != nil { 119 return err 120 } 121 pointerSlice.Index(i).Set(item.Elem()) 122 } 123 } 124 pointerRv.Set(pointerSlice) 125 return 126 }