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  }