github.com/yaoapp/kun@v0.9.0/any/map.go (about)

     1  package any
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  
     7  	"github.com/yaoapp/kun/maps"
     8  	"github.com/yaoapp/kun/share"
     9  )
    10  
    11  // Map the replacement for Maps.Map
    12  type Map struct {
    13  	maps.MapStrAny
    14  }
    15  
    16  // MakeMap create a new  map instance
    17  func MakeMap() Map {
    18  	return Map{MapStrAny: maps.MapStrAnyOf(map[string]interface{}{})}
    19  }
    20  
    21  // MapOf create a new map instance
    22  func MapOf(values interface{}) Map {
    23  	if values == nil {
    24  		return MakeMap()
    25  	}
    26  	switch values.(type) {
    27  	case map[string]interface{}:
    28  		return Map{MapStrAny: maps.MapStrAnyOf(values.(map[string]interface{}))}
    29  	}
    30  
    31  	// converts to map
    32  	reflectValues := reflect.ValueOf(values)
    33  	reflectValues = reflect.Indirect(reflectValues)
    34  	if reflectValues.Kind() == reflect.Map {
    35  		valuesMap := map[string]interface{}{}
    36  		for _, key := range reflectValues.MapKeys() {
    37  			k := fmt.Sprintf("%v", key)
    38  			valuesMap[k] = reflectValues.MapIndex(key).Interface()
    39  		}
    40  		return Map{MapStrAny: maps.MapStrAnyOf(valuesMap)}
    41  	} else if reflectValues.Kind() == reflect.Struct {
    42  		valuesMap := map[string]interface{}{}
    43  		typeOfS := reflectValues.Type()
    44  		for i := 0; i < reflectValues.NumField(); i++ {
    45  			name := share.GetTagName(typeOfS.Field(i), "json")
    46  			valuesMap[name] = reflectValues.Field(i).Interface()
    47  		}
    48  		return Map{MapStrAny: maps.MapStrAnyOf(valuesMap)}
    49  	}
    50  
    51  	panic(fmt.Sprintf("v is %s not a type of map", reflectValues.Kind()))
    52  }
    53  
    54  // Any returns the value stored in the map for a key.
    55  func (m Map) Any(key string) *Any {
    56  	return Of(m.Get(key))
    57  }
    58  
    59  // Flatten The Flatten method is alias of Dot, to flatten a multi-dimensional map[string]inteface{} into a single level  map[string]inteface{}
    60  // that uses "dot" notation to indicate depth
    61  func (m Map) Flatten() Map {
    62  	return m.Dot()
    63  }
    64  
    65  // Dot The Dot method flattens a multi-dimensional map[string]inteface{} into a single level  map[string]inteface{}
    66  // that uses "dot" notation to indicate depth
    67  func (m Map) Dot() Map {
    68  	res := MakeMap()
    69  	m.Range(func(key string, value interface{}) bool {
    70  		res.dotSet(key, value)
    71  		return true
    72  	})
    73  	return res
    74  }
    75  
    76  // dotSet set the value for a key uses "dot" notation
    77  func (m Map) dotSet(key string, value interface{}) {
    78  
    79  	m.Set(key, value)
    80  
    81  	reflectValue := reflect.ValueOf(value)
    82  	reflectValue = reflect.Indirect(reflectValue)
    83  	valueKind := reflectValue.Kind()
    84  
    85  	if valueKind == reflect.Slice || valueKind == reflect.Array { // Slice || Array
    86  		for i := 0; i < reflectValue.Len(); i++ {
    87  			m.dotSet(fmt.Sprintf("%s.%d", key, i), reflectValue.Index(i).Interface())
    88  		}
    89  
    90  	} else if valueKind == reflect.Map { // Map
    91  		for _, sub := range reflectValue.MapKeys() {
    92  			m.dotSet(fmt.Sprintf("%s.%v", key, sub), reflectValue.MapIndex(sub).Interface())
    93  		}
    94  	}
    95  }