gitee.com/zhongguo168a/gocodes@v0.0.0-20230609140523-e1828349603f/datax/mapx/map-interface.go (about) 1 package mapx 2 3 import ( 4 "gitee.com/zhongguo168a/gocodes/datax/convertx" 5 "sort" 6 "strconv" 7 "strings" 8 "sync" 9 ) 10 11 var ( 12 mu sync.RWMutex 13 ) 14 15 func Keys(t map[string]interface{}) (r []string) { 16 17 for key := range t { 18 r = append(r, key) 19 } 20 21 sort.Strings(r) 22 return 23 } 24 25 func Set(t map[string]interface{}, key string, val interface{}) { 26 old := t[key] 27 if old == nil { 28 switch data := val.(type) { 29 case map[string]interface{}: 30 m := map[string]interface{}{} 31 t[key] = m 32 for dk, dv := range data { 33 m[dk] = dv 34 } 35 default: 36 t[key] = val 37 } 38 } else { 39 switch data := old.(type) { 40 case map[string]interface{}: 41 if val == nil { 42 t[key] = val 43 } else { 44 m := val.(map[string]interface{}) 45 for dk, dv := range m { 46 data[dk] = dv 47 } 48 } 49 default: 50 t[key] = val 51 } 52 } 53 } 54 55 func HasKeys(t map[string]interface{}, keys ...string) bool { 56 var has bool 57 var m interface{} 58 cur := t 59 60 for i, k := range keys { 61 m, has = cur[k] 62 if has == false { 63 return false 64 } 65 66 cur, has = m.(map[string]interface{}) 67 if has == false && i == len(keys)-1 { 68 return true 69 } 70 } 71 72 return true 73 } 74 75 func Has(t map[string]interface{}, key string) bool { 76 _, ok := t[key] 77 return ok 78 } 79 80 func Interface(t map[string]interface{}, key string) (r interface{}) { 81 if t == nil { 82 return 83 } 84 85 ir, ok := t[key] 86 if ok == false { 87 return 88 } 89 90 r = ir 91 return 92 } 93 94 func String(t map[string]interface{}, key string) (r string) { 95 if t == nil { 96 return 97 } 98 99 ir, ok := t[key] 100 if ok == false { 101 return 102 } 103 104 r, ok = ir.(string) 105 if ok == false { 106 return 107 } 108 return 109 } 110 111 func StringDefault(t map[string]interface{}, key string, dflt string) (r string) { 112 if t == nil { 113 return dflt 114 } 115 116 ir, ok := t[key] 117 if ok == false { 118 return dflt 119 } 120 121 r, ok = ir.(string) 122 if ok == false { 123 return 124 } 125 return 126 } 127 128 func Int(t map[string]interface{}, key string) (r int) { 129 if t == nil { 130 return 131 } 132 133 ir, ok := t[key] 134 if ok == false { 135 return 136 } 137 138 r = int(convertx.AnyToInt64(ir)) 139 return 140 } 141 142 func IntDefault(t map[string]interface{}, key string, dflt int) (r int) { 143 if t == nil { 144 return dflt 145 } 146 147 ir, ok := t[key] 148 if ok == false { 149 return dflt 150 } 151 152 r = int(convertx.AnyToInt64(ir)) 153 return 154 } 155 156 func Float64(t map[string]interface{}, key string) (r float64) { 157 if t == nil { 158 return 159 } 160 161 ir, ok := t[key] 162 if ok == false { 163 return 164 } 165 166 r = convertx.AnyToFloat64(ir) 167 return 168 } 169 170 func Float64Default(t map[string]interface{}, key string, dflt float64) (r float64) { 171 if t == nil { 172 return dflt 173 } 174 175 ir, ok := t[key] 176 if ok == false { 177 return dflt 178 } 179 180 r = convertx.AnyToFloat64(ir) 181 return 182 } 183 184 func Bool(t map[string]interface{}, key string) (r bool) { 185 if t == nil { 186 return 187 } 188 189 ir, ok := t[key] 190 if ok == false { 191 return 192 } 193 r = convertx.AnyToBool(ir) 194 return 195 } 196 197 func BoolDefault(t map[string]interface{}, key string, dflt bool) (r bool) { 198 if t == nil { 199 return dflt 200 } 201 202 ir, ok := t[key] 203 if ok == false { 204 return dflt 205 } 206 r = convertx.AnyToBool(ir) 207 return 208 } 209 210 var mutex = sync.RWMutex{} 211 212 func Map(t map[string]interface{}, key string) (r map[string]interface{}) { 213 if t == nil { 214 return 215 } 216 217 mutex.RLock() 218 ir, ok := t[key] 219 mutex.RUnlock() 220 if ok == false { 221 mutex.Lock() 222 r = map[string]interface{}{} 223 t[key] = r 224 mutex.Unlock() 225 return 226 } 227 228 if ir == nil { 229 return 230 } 231 232 r = ir.(map[string]interface{}) 233 return 234 } 235 236 // path = "/a/b/c" 237 func DeleteByPath(t map[string]interface{}, path string) { 238 if t == nil { 239 return 240 } 241 if string(path[0]) != "/" { 242 panic("路径的首字符必须为/") 243 } 244 path = path[1:] 245 arr := strings.Split(path, "/") 246 curmap := t 247 curkey := "" 248 for { 249 if len(arr) == 1 { 250 break 251 } 252 curkey = arr[0] 253 arr = arr[1:] 254 255 ir, ok := curmap[curkey] 256 if ok == false { 257 r := map[string]interface{}{} 258 curmap[curkey] = r 259 ir = r 260 } 261 curmap = ir.(map[string]interface{}) 262 } 263 264 delete(curmap, arr[0]) 265 } 266 267 // path = "/a/b/c" 268 func SetByPath(t map[string]interface{}, path string, value interface{}) { 269 if t == nil { 270 return 271 } 272 if string(path[0]) != "/" { 273 panic("路径的首字符必须为/") 274 } 275 path = path[1:] 276 arr := strings.Split(path, "/") 277 curmap := t 278 curkey := "" 279 for { 280 if len(arr) == 1 { 281 break 282 } 283 curkey = arr[0] 284 arr = arr[1:] 285 286 ir, ok := curmap[curkey] 287 if ok == false { 288 r := map[string]interface{}{} 289 curmap[curkey] = r 290 ir = r 291 } 292 curmap = ir.(map[string]interface{}) 293 } 294 295 curmap[arr[0]] = value 296 } 297 298 // path = "/a/b/c/.." 299 func MapByPath(t map[string]interface{}, path string) (r map[string]interface{}) { 300 if t == nil { 301 return 302 } 303 if string(path[0]) != "/" { 304 panic("路径的首字符必须为/") 305 } 306 path = path[1:] 307 arr := strings.Split(path, "/") 308 309 curmap := t 310 curkey := "" 311 for { 312 if len(arr) == 0 { 313 return 314 } 315 curkey = arr[0] 316 arr = arr[1:] 317 318 ir, ok := t[curkey] 319 if ok == false { 320 r = map[string]interface{}{} 321 curmap[curkey] = r 322 ir = r 323 } 324 r = ir.(map[string]interface{}) 325 curmap = r 326 } 327 return 328 } 329 330 // 获取map的array, 如果不存在就创建一个 331 func Array(t map[string]interface{}, key string) (r []interface{}) { 332 if t == nil { 333 return 334 } 335 336 ir, ok := t[key] 337 if ok == false { 338 r = []interface{}{} 339 t[key] = r 340 return 341 } 342 343 if ir == nil { 344 return 345 } 346 347 r = ir.([]interface{}) 348 349 return 350 } 351 352 func Flat(t map[string]interface{}, detail bool) map[string]interface{} { 353 if t == nil { 354 return nil 355 } 356 357 result := map[string]interface{}{} 358 flat(t, detail, result, "") 359 return result 360 } 361 func flat(iValue interface{}, detail bool, result map[string]interface{}, path string) { 362 switch v := iValue.(type) { 363 case map[string]interface{}: 364 if v != nil { 365 if detail { 366 if path == "" { 367 result["/"] = len(v) 368 } else { 369 result[path] = len(v) 370 } 371 } 372 var keys []string 373 for key, val := range v { 374 keys = append(keys, key) 375 flat(val, detail, result, path+"/"+key) 376 } 377 result[path+"/keys"] = keys 378 } else { 379 if detail { 380 result[path] = nil 381 } 382 } 383 384 case []interface{}: 385 if detail { 386 if path == "" { 387 result["/"] = len(v) 388 } else { 389 result[path] = len(v) 390 } 391 } 392 for i, val := range v { 393 flat(val, detail, result, path+"/"+strconv.Itoa(i)) 394 } 395 default: 396 result[path] = iValue 397 } 398 } 399 400 type IFromMap interface { 401 FromMap(m map[string]interface{}, args ...interface{}) 402 } 403 404 func StructFromValue(st IFromMap, val interface{}, args ...interface{}) IFromMap { 405 m, ok := val.(map[string]interface{}) 406 if ok == true { 407 st.FromMap(m, args...) 408 } 409 return st 410 } 411 412 var NewMap = map[string]func(args ...interface{}) interface{}{} 413 414 func StructFromByType(val interface{}, args ...interface{}) (r interface{}) { 415 bm, ok := val.(map[string]interface{}) 416 if ok && Has(bm, "_type") { 417 typ := String(bm, "_type") 418 newFunc, has := NewMap[typ] 419 if has == false { 420 r = val 421 } else { 422 r = newFunc(args...) 423 fm := r.(IFromMap) 424 fm.FromMap(bm, args...) 425 } 426 } else { 427 r = val 428 } 429 return 430 } 431 432 func StructFromByInterface(target, val interface{}, args ...interface{}) (r interface{}) { 433 switch v := val.(type) { 434 case map[string]interface{}: 435 if t, ok := target.(map[string]interface{}); ok == false { 436 t = map[string]interface{}{} 437 target = t 438 Copy(v, t) 439 } else { 440 Copy(v, t) 441 } 442 default: 443 target = val 444 } 445 446 return target 447 } 448 449 type IToMap interface { 450 ToMap(m map[string]interface{}, args ...interface{}) 451 } 452 type IToMapAll interface { 453 ToMapAll(m map[string]interface{}, args ...interface{}) 454 } 455 456 type IStructName interface { 457 StructName() string 458 } 459 460 func StructToValueNotNull(st IToMap, args ...interface{}) (r interface{}) { 461 if st != nil { 462 a := map[string]interface{}{} 463 if stname, ok := st.(IStructName); ok { 464 a["_type"] = stname.StructName() 465 } 466 st.ToMap(a, args...) 467 r = a 468 } 469 return 470 } 471 472 func StructToValue(st IToMap, val interface{}, name string, args ...interface{}) { 473 m, ok := val.(map[string]interface{}) 474 if ok == true { 475 if st != nil { 476 a := map[string]interface{}{} 477 m[name] = a 478 st.ToMap(a, args...) 479 } 480 } 481 return 482 } 483 484 func StructToByType(val interface{}, args ...interface{}) (r interface{}) { 485 486 toval, ok := val.(IToMap) 487 if ok { 488 m := map[string]interface{}{} 489 toval.ToMap(m, args...) 490 if stname, ok := toval.(IStructName); ok { 491 m["_type"] = stname.StructName() 492 } 493 r = m 494 } else { 495 switch v := val.(type) { 496 case []interface{}: 497 r = cloneArray(v, []interface{}{}, true) 498 case map[string]interface{}: 499 m := map[string]interface{}{} 500 r = cloneAny(v, m, true) 501 default: 502 r = v 503 } 504 } 505 506 return 507 } 508 509 func ArrayByMap(val interface{}, handler func(length int, keys []int, items []interface{})) (r []interface{}) { 510 var keys []int 511 var items []interface{} 512 switch b := val.(type) { 513 case map[string]interface{}: 514 var max int64 = -1 515 for key, item := range b { 516 k := convertx.AnyToInt64(key) 517 keys = append(keys, int(k)) 518 items = append(items, item) 519 520 if k > max { 521 max = k 522 } 523 } 524 handler(int(max)+1, keys, items) 525 case []interface{}: 526 for i, item := range b { 527 keys = append(keys, int(i)) 528 items = append(items, item) 529 } 530 handler(len(b), keys, items) 531 } 532 return 533 }