package json import ( "encoding/json" "fmt" "log" "reflect" "strconv" ) // Map type type Map map[string]interface{} func IsMap(val any) (res Map, check bool) { switch tv := val.(type) { case map[string]any: res, check = Map(tv), true case Map: res, check = tv, true default: res = nil } return } // New init Map object func NewMap() Map { return make(Map) } // FromInterface convert map[string]interface{} or Map interface to Map func MapFromInterface(iface interface{}) (res Map) { switch val := iface.(type) { case map[string]interface{}: res = FromMap(val) case Map: res = val default: res = NewMap() } return } // FromMap convert map[string]interface{} to Map object func FromMap(m map[string]interface{}) Map { return Map(m) } // Bool returns bool value by key func (s Map) Bool(key string, defaultVal bool) bool { if res, check := s[key].(bool); check { return res } return defaultVal } // KeyExists check value exists by key func (s Map) KeyExists(key string) bool { _, check := s[key] return check } // KeysExists check values exists by keys list. // Returns the first blank key found. // If all keys are defined, an empty string will be returned func (s Map) KeysExists(keys []string) string { for _, key := range keys { if _, check := s[key]; !check { return key } } return "" } func val(l, r interface{}) (res reflect.Value) { lVal, rVal := reflect.ValueOf(l), reflect.ValueOf(r) if lVal.Kind() == reflect.Ptr && rVal.Kind() != reflect.Ptr { return val(lVal.Elem().Interface(), r) } defer func() { if r := recover(); r != nil { res = rVal } }() res = lVal.Convert(rVal.Type()) return } func isType(l, r any) bool { if l == nil || r == nil { return false } rType := reflect.ValueOf(r).Type() lType := reflect.ValueOf(l).Type() //log.Println(rType, lType, reflect.ValueOf(iface).Convert(rType)) return lType.ConvertibleTo(rType) } func (s Map) IsNil(key string) bool { if iface, check := s[key]; check { return iface == nil } return false } func (s Map) IsInt(key string) bool { if iface, check := s[key]; check { return isType(iface, int(0)) } return false } func (s Map) IsBoolean(key string) bool { if iface, check := s[key]; check { return isType(iface, false) } return false } func (s Map) Byte(key string, defaultVal byte) byte { if iface, check := s[key]; check { return byte(val(iface, defaultVal).Int()) } return defaultVal } // Int returns int64 value by key. // If key isn't defined will be returned defaultVal arg value func (s Map) Int(key string, defaultVal int64) int64 { if iface, check := s[key]; check { return val(iface, defaultVal).Int() } return defaultVal } func (s Map) Int32(key string, defaultVal int) int { if iface, check := s[key]; check { return val(iface, defaultVal).Interface().(int) } return defaultVal } func (s Map) Float32(key string, defaultVal float32) float32 { if iface, check := s[key]; check { return val(iface, defaultVal).Interface().(float32) } return defaultVal } func (s Map) Float64(key string, defaultVal float64) float64 { if iface, check := s[key]; check { return val(iface, defaultVal).Interface().(float64) } return defaultVal } // Value returns interface object with attempt to convert to defaultVal type. // If key isn't defined will be returned defaultVal arg value func (s Map) Value(key string, defaultVal interface{}) interface{} { // check value exists by key if iface, check := s[key]; check { // check defaultVal is valid dVal := reflect.ValueOf(defaultVal) if !dVal.IsValid() { // invalid, return arrived interface return iface } // defaultVal is valid, attempt to convert found value to defaultVal type lVal := reflect.ValueOf(iface) switch { case !lVal.IsValid(): return defaultVal // invalid found value, return defaultVal case lVal.Kind() == dVal.Kind(): return iface // types of found value and defaultVal is match. return found value case lVal.Type().ConvertibleTo(dVal.Type()): return lVal.Convert(dVal.Type()).Interface() // found value type can be converted to defaultVal type. return converted found value default: { // found value type can't be converted to defaultVal type. If found value is string, attempt to convert to number value if lVal.Kind() == reflect.String { switch dVal.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: val, err := strconv.Atoi(lVal.String()) if err != nil { return defaultVal } lVal = reflect.ValueOf(val) return lVal.Convert(dVal.Type()) case reflect.Float32, reflect.Float64: val, err := strconv.ParseFloat(lVal.String(), 64) if err != nil { return defaultVal } lVal = reflect.ValueOf(val) return lVal.Convert(dVal.Type()) } } } } } return defaultVal } // ValueJSON returns json source object by key // If key isn't defined will be returned defaultVal arg value func (s Map) ValueJSON(key string, defaultVal []byte) (res []byte) { res = defaultVal if s.KeyExists(key) { if r, err := json.Marshal(s[key]); err == nil { res = r } } return } // String returns string value by key // If key isn't defined will be returned defaultVal arg value func (s Map) String(key, defaultVal string) string { if iface, check := s[key]; check { return val(iface, defaultVal).String() } return defaultVal } func (s Map) EachSlice(key string, each func(int, any) bool) { sl := s.Slice(key, []any{}) for i, val := range sl { if !each(i, val) { return } } } func (s Map) EachMap(key string, each func(int, Map) bool) { s.EachSlice(key, func(i int, val any) bool { switch val.(type) { case map[string]any: return each(i, Map(val.(map[string]any))) case Map: return each(i, val.(Map)) default: return true } }) } func (s Map) StringWithError(key, defaultVal string) (string, error) { if iface, check := s[key]; check { val := val(iface, defaultVal).String() if val == defaultVal { return defaultVal, fmt.Errorf("FIELD [%s] IS EMPTY", key) } return val, nil } return defaultVal, fmt.Errorf("FIELD [%s] IS NOT EXISTS", key) } func (s Map) Bytes(key string, defaultVal []byte) []byte { if iface, check := s[key]; check { return []byte(val(iface, defaultVal).String()) } return defaultVal } func (s Map) BytesWithError(key string, defaultVal []byte) ([]byte, error) { if iface, check := s[key]; check { return []byte(val(iface, defaultVal).String()), nil } return defaultVal, fmt.Errorf("FIELD [%s] IS NOT EXISTS", key) } func (s Map) StringVal(key, defaultVal string) string { if iface, check := s[key]; check { return fmt.Sprint(iface) } return defaultVal } // Slce returns slice of interface{} by key // If key isn't defined or have a different type will be returned defaultVal arg value func (s Map) Slice(key string, defaultVal []interface{}) (res []interface{}) { if arr, check := s[key].([]interface{}); check { res = arr } else { res = defaultVal } return } // StringSlice returns string slice by key // If key isn't defined will be returned defaultVal arg value func (s Map) StringSlice(key string, defaultVal []string) (res []string) { if arr, check := s[key].([]interface{}); check { res = make([]string, len(arr)) for i, v := range arr { res[i] = fmt.Sprint(v) } } else { res = defaultVal } return } // Map returns Map object by key // If key isn't defined or have other type will be returned defaultVal arg value func (s Map) Map(key string, defaultVal Map) (res Map) { val := s[key] switch iface := val.(type) { case Map: res = iface case map[string]interface{}: res = Map(iface) default: res = defaultVal } return } // JSON returns JSON source of the self object func (s Map) JSON() (res []byte) { res, _ = json.Marshal(s) return } // JSONIndent returns JSON source of the self object with indent func (s Map) JSONIndent(prefix, indent string) (res []byte) { res, _ = json.MarshalIndent(s, prefix, indent) return } func (s Map) JSONString() (res string) { if data, err := json.Marshal(s); err == nil { res = string(data) } return } func (s Map) JSONPrettyString() (res string) { if data, err := json.MarshalIndent(s, "", "\t"); err == nil { res = string(data) } return } func (s Map) LogPretty() { log.Println(s.JSONPrettyString()) } // ToMap returns map[string]interface{} of the self object func (s Map) ToMap() map[string]interface{} { return map[string]interface{}(s) } // Copy returns copied map (todo dipcopy) func (s Map) Copy() (res Map) { res = make(Map) for key, val := range s { res[key] = val } return } func (s Map) IsEmpty() bool { return len(s) == 0 } func (s Map) Update(m Map) { for key, val := range m { s[key] = val } } func (s Map) StorePtr(key string, val interface{}) interface{} { s[key] = &val return &val } func (s Map) Variable(key string, ptr interface{}) bool { val, check := s[key] if !check { // value is not exists return false } vVal := reflect.ValueOf(ptr) if vVal.Kind() != reflect.Ptr { // ptr is not a pointer return false } vElem := vVal.Elem() rVal := reflect.ValueOf(val) if !rVal.CanConvert(vElem.Type()) { // type is not converted return false } vElem.Set(rVal.Convert(vElem.Type())) return true }