github.com/yaoapp/kun@v0.9.0/maps/strany.go (about) 1 package maps 2 3 import ( 4 "fmt" 5 "reflect" 6 "sort" 7 "strings" 8 9 "github.com/yaoapp/kun/interfaces" 10 "github.com/yaoapp/kun/share" 11 ) 12 13 // Map alias of MapStrAny 14 type Map = MapStrAny 15 16 // Str alias of MapStrAny 17 type Str = MapStrAny 18 19 // StrAny alias of MapStrAny 20 type StrAny = MapStrAny 21 22 // MapStr alias of MapStrAny 23 type MapStr = MapStrAny 24 25 // MapStrAny type of map[string}]inteface{} 26 type MapStrAny map[string]interface{} 27 28 // Make create a new instance (the default type of map) 29 func Make() MapStrAny { 30 return MakeMapStrAny() 31 } 32 33 // MakeMap create a new instance 34 func MakeMap() MapStrAny { 35 return MakeMapStrAny() 36 } 37 38 // MakeMapStr create a new instance 39 func MakeMapStr() MapStrAny { 40 return MakeMapStrAny() 41 } 42 43 // MakeStr create a new instance 44 func MakeStr() MapStrAny { 45 return MakeMapStrAny() 46 } 47 48 // MakeStrAny create a new instance 49 func MakeStrAny() MapStrAny { 50 return MakeMapStrAny() 51 } 52 53 // MakeMapStrAny create a new instance 54 func MakeMapStrAny() MapStrAny { 55 return MapStrAny{} 56 } 57 58 // Of create a new instance (the default type of map) 59 func Of(values map[string]interface{}) MapStrAny { 60 return MapStrAnyOf(values) 61 } 62 63 // MapOf create a new instance 64 func MapOf(values map[string]interface{}) MapStrAny { 65 return MapStrAnyOf(values) 66 } 67 68 // MapStrOf create a new instance 69 func MapStrOf(values map[string]interface{}) MapStrAny { 70 return MapStrAnyOf(values) 71 } 72 73 // StrOf create a new instance 74 func StrOf(values map[string]interface{}) MapStrAny { 75 return MapStrAnyOf(values) 76 } 77 78 // StrAnyOf create a new instance 79 func StrAnyOf(values map[string]interface{}) MapStrAny { 80 return MapStrAnyOf(values) 81 } 82 83 // MapStrAnyOf create a new instance (the default type of map) 84 func MapStrAnyOf(values map[string]interface{}) MapStrAny { 85 m := MakeMapStrAny() 86 for key, value := range values { 87 m.Set(key, value) 88 } 89 return m 90 } 91 92 // Flatten The Flatten method is alias of Dot, to flatten a multi-dimensional map[string]inteface{} into a single level map[string]inteface{} 93 // that uses "dot" notation to indicate depth 94 func (m MapStrAny) Flatten() MapStrAny { 95 return m.Dot() 96 } 97 98 // UnFlatten The UnFlatten method unflatten a single level map[string]inteface{} into multi-dimensional map[string]inteface{} 99 // that uses "dot" notation to indicate depth 100 func (m MapStrAny) UnFlatten() MapStrAny { 101 return m.UnDot() 102 } 103 104 // Dot The Dot method flattens a multi-dimensional map[string]inteface{} into a single level map[string]inteface{} 105 // that uses "dot" notation to indicate depth 106 func (m MapStrAny) Dot() MapStrAny { 107 res := MakeMapStrAny() 108 m.Range(func(key string, value interface{}) bool { 109 res.dotSet(key, value) 110 return true 111 }) 112 return res 113 } 114 115 // dotSet set the value for a key uses "dot" notation 116 func (m MapStrAny) dotSet(key string, value interface{}) { 117 118 reflectValue := reflect.ValueOf(value) 119 reflectValue = reflect.Indirect(reflectValue) 120 valueKind := reflectValue.Kind() 121 122 if valueKind == reflect.Slice || valueKind == reflect.Array { // Slice || Array 123 for i := 0; i < reflectValue.Len(); i++ { 124 m.dotSet(fmt.Sprintf("%s.%d", key, i), reflectValue.Index(i).Interface()) 125 } 126 127 } else if valueKind == reflect.Map { // Map 128 for _, sub := range reflectValue.MapKeys() { 129 m.dotSet(fmt.Sprintf("%s.%v", key, sub), reflectValue.MapIndex(sub).Interface()) 130 } 131 132 } else if valueKind == reflect.Struct { // Struct 133 134 if toMap := reflect.ValueOf(value).MethodByName("ToMap"); toMap.IsValid() { 135 args := []reflect.Value{} 136 values := toMap.Call(args) 137 if len(values) == 1 { 138 v, ok := values[0].Interface().(map[string]interface{}) 139 if ok { 140 m.dotSet(key, v) 141 } 142 } 143 return 144 } 145 146 // auto struct 147 typeOfS := reflectValue.Type() 148 for i := 0; i < reflectValue.NumField(); i++ { 149 sub := share.GetTagName(typeOfS.Field(i), "json") 150 if reflectValue.Field(i).CanInterface() { 151 v := reflectValue.Field(i).Interface() 152 m.dotSet(fmt.Sprintf("%s.%v", key, sub), v) 153 } 154 } 155 } 156 157 m.Set(key, value) 158 } 159 160 // UnDot The UnDot method unflatten a single level map[string]inteface{} into multi-dimensional map[string]inteface{} 161 // that uses "dot" notation to indicate depth 162 func (m MapStrAny) UnDot() MapStrAny { 163 res := MakeMapStrAny() 164 m.Range(func(key string, value interface{}) bool { 165 res.SetUnDot(key, value) 166 return true 167 }) 168 return res 169 } 170 171 // SetUnDot set the value for a key uses "dot" notation 172 func (m MapStrAny) SetUnDot(key string, value interface{}) { 173 if !strings.Contains(key, ".") { 174 m.Set(key, value) 175 return 176 } 177 178 keys := strings.Split(key, ".") 179 tail := strings.Join(keys[1:], ".") 180 v, ok := m.Get(keys[0]).(MapStrAny) 181 if !ok { 182 v = MapStrAny{} 183 } 184 v[tail] = value 185 186 v.Range(func(key string, value interface{}) bool { 187 v.SetUnDot(key, value) 188 return true 189 }) 190 191 m.Set(keys[0], v) 192 m.Del(key) 193 } 194 195 // Set set the value for a key 196 func (m MapStrAny) Set(key string, value interface{}) { 197 m[key] = value 198 } 199 200 // Get returns the value stored in the map for a key, or nil if no value is present. 201 func (m MapStrAny) Get(key string) interface{} { 202 return m[key] 203 } 204 205 // Has return true whether value was found in the map. 206 func (m MapStrAny) Has(key string) bool { 207 _, has := m[key] 208 return has 209 } 210 211 // Del deletes the value for a key. 212 func (m MapStrAny) Del(key string) { 213 delete(m, key) 214 } 215 216 // GetOrSet returns the existing value for the key if present. Otherwise, it stores and returns the given value. 217 func (m MapStrAny) GetOrSet(key string, value interface{}) interface{} { 218 if res, has := m[key]; has { 219 return res 220 } 221 m.Set(key, value) 222 return value 223 } 224 225 // GetAndDel deletes the value for a key, returning the previous value if any. The loaded result reports whether the key was present. 226 func (m MapStrAny) GetAndDel(key string) interface{} { 227 if res, has := m[key]; has { 228 m.Del(key) 229 return res 230 } 231 return nil 232 } 233 234 // Len returns the length of the map. 235 func (m MapStrAny) Len() int { 236 return len(m) 237 } 238 239 // Range calls f sequentially for each key and value present in the map. If f returns false, range stops the iteration. 240 func (m MapStrAny) Range(cb func(key string, value interface{}) bool) { 241 for key, value := range m { 242 if !cb(key, value) { 243 break 244 } 245 } 246 } 247 248 // Keys returns all keys of the map as a slice. 249 func (m MapStrAny) Keys() []string { 250 keys := []string{} 251 m.Range(func(key string, value interface{}) bool { 252 keys = append(keys, key) 253 return true 254 }) 255 sort.Strings(keys) 256 return keys 257 } 258 259 // Values returns all values of the map as a slice. 260 func (m MapStrAny) Values() []interface{} { 261 values := []interface{}{} 262 keys := m.Keys() 263 for _, key := range keys { 264 values = append(values, m.Get(key)) 265 } 266 return values 267 } 268 269 // IsEmpty checks whether the map is empty. It returns true if map is empty, or else false. 270 func (m MapStrAny) IsEmpty() bool { 271 return len(m) == 0 272 } 273 274 // Merge merges hash maps 275 func (m MapStrAny) Merge(maps ...interfaces.MapStrAny) { 276 for _, new := range maps { 277 new.Range(func(key string, value interface{}) bool { 278 m.Set(key, value) 279 return true 280 }) 281 } 282 }