package utils import ( "bytes" "encoding/json" "errors" "fmt" "math" "net/url" "reflect" "strconv" "strings" "time" "git.rosy.net.cn/baseapi" "github.com/gazeboxu/structs" "github.com/mitchellh/mapstructure" ) var ( DefaultTimeValue = Str2Time("1970-01-01 00:00:00") ZeroTimeValue = time.Time{} ) func UnmarshalUseNumber(data []byte, result interface{}) error { err := TryUnmarshalUseNumber(data, result) if err != nil { baseapi.SugarLogger.Infof("decode data:%v, error:%v", string(data), err) } return err } func TryUnmarshalUseNumber(data []byte, result interface{}) error { d := json.NewDecoder(bytes.NewReader(data)) d.UseNumber() return d.Decode(result) } // 这个函数将解析json,返回的map中的字段类型与structObj中的完全一样的 func Unmarshal2Map(data []byte, structObj interface{}) (resultMap map[string]interface{}, err error) { if err = json.Unmarshal(data, structObj); err == nil { if err = json.Unmarshal(data, &resultMap); err == nil { m := Struct2MapByJson(structObj) for k := range resultMap { if value, ok := m[k]; ok { resultMap[k] = value } else { delete(resultMap, k) } } } } return resultMap, err } func MustMarshal(obj interface{}) []byte { byteArr, err := json.Marshal(obj) if err != nil { panic(fmt.Sprintf("err when Marshal obj:%v with error:%v", obj, err)) } return byteArr } func TryInterface2Int64(data interface{}) (num int64, err error) { if data == nil { return num, errors.New("data is nil") } if dataNumber, ok := data.(int64); ok { return dataNumber, nil } if dataNumber, ok := data.(int); ok { return int64(dataNumber), nil } if dataNumber, ok := data.(int32); ok { return int64(dataNumber), nil } if dataNumber, ok := data.(int16); ok { return int64(dataNumber), nil } if dataNumber, ok := data.(int8); ok { return int64(dataNumber), nil } if dataNumber, ok := data.(json.Number); ok { return dataNumber.Int64() } if str, ok := data.(string); ok { return Str2Int64WithDefault(str, 0), nil } return 0, fmt.Errorf("data is not json.Number, it's %s, value:%v", reflect.TypeOf(data).String(), data) } func MustInterface2Int64(data interface{}) int64 { retVal, err := TryInterface2Int64(data) if err != nil { panic(err.Error()) } return retVal } func Interface2Int64WithDefault(data interface{}, defValue int64) int64 { retVal, err := TryInterface2Int64(data) if err != nil { return defValue } return retVal } func ForceInterface2Int64(data interface{}) int64 { if dataStr, ok := data.(string); ok { return Str2Int64(dataStr) } return Interface2Int64WithDefault(data, 0) } func TryInterface2Float64(data interface{}) (num float64, err error) { if data == nil { return num, errors.New("data is nil") } if dataNumber, ok := data.(float64); ok { return dataNumber, nil } if dataNumber, ok := data.(float32); ok { return float64(dataNumber), nil } if dataNumber, ok := data.(json.Number); ok { return dataNumber.Float64() } if str, ok := data.(string); ok { return Str2Float64WithDefault(str, 0), nil } return 0, fmt.Errorf("data is not json.Number, it's %s, value:%v", reflect.TypeOf(data).String(), data) } func MustInterface2Float64(data interface{}) float64 { retVal, err := TryInterface2Float64(data) if err != nil { panic(err.Error()) } return retVal } func Interface2Float64WithDefault(data interface{}, defValue float64) (retVal float64) { retVal, err := TryInterface2Float64(data) if err != nil { return defValue } return retVal } func Interface2String(data interface{}) string { if data == nil { return "" } return data.(string) } func Interface2Int64List(data interface{}) []int64 { if data == nil { return nil } list := data.([]interface{}) retVal := make([]int64, len(list)) for k, v := range list { retVal[k] = MustInterface2Int64(v) } return retVal } func Interface2StringList(data interface{}) []string { if data == nil { return nil } list := data.([]interface{}) retVal := make([]string, len(list)) for k, v := range list { retVal[k] = Interface2String(v) } return retVal } func Slice2MapSlice(data []interface{}) []map[string]interface{} { retVal := make([]map[string]interface{}, len(data)) for k, v := range data { retVal[k] = v.(map[string]interface{}) } return retVal } func Slice2int64Slice(data []interface{}) []int64 { retVal := make([]int64, len(data)) for k, v := range data { retVal[k] = MustInterface2Int64(v) } return retVal } func Slice2StringSlice(data []interface{}) []string { retVal := make([]string, len(data)) for k, v := range data { retVal[k] = Interface2String(v) } return retVal } // func Bool2String(value bool) string { if value { return "true" } return "false" } func Bool2Int(value bool) int { if value { return 1 } return 0 } func Str2Int64WithDefault(str string, defValue int64) int64 { retVal, err := strconv.ParseInt(str, 10, 64) if err != nil { return defValue } return retVal } func Str2Int64(str string) int64 { retVal, err := strconv.ParseInt(str, 10, 64) if err != nil { baseapi.SugarLogger.Errorf("error when convert %s to int64", str) } return retVal } func Str2Float64WithDefault(str string, defValue float64) float64 { retVal, err := strconv.ParseFloat(str, 64) if err != nil { retVal = defValue } return retVal } func Str2Float64(str string) float64 { retVal, err := strconv.ParseFloat(str, 64) if err != nil { baseapi.SugarLogger.Errorf("error when convert %s to float64", str) } return retVal } func Int64ToStr(value int64) string { return strconv.FormatInt(value, 10) } func Int64ToStrNoZero(value int64) string { if value == 0 { return "" } return strconv.FormatInt(value, 10) } func Int2Str(value int) string { return strconv.Itoa(value) } func Float64TwoInt64(data float64) int64 { return int64(math.Round(data)) } func Float64ToStr(data float64) string { return fmt.Sprint(data) } // timestamp is in second func Timestamp2Str(timestamp int64) string { return Time2Str(Timestamp2Time(timestamp)) } func Timestamp2Time(timestamp int64) time.Time { const normalTimestamp = 1533709322 if timestamp > normalTimestamp*100 { // 传成毫秒了 baseapi.SugarLogger.Errorf("Timestamp2Time wrong timestamp:%d", timestamp) timestamp = timestamp / 1000 } return time.Unix(timestamp, 0) } func Time2Str(t time.Time) string { return t.Format("2006-01-02 15:04:05") } func Time2TimeStr(t time.Time) string { return t.Format("15:04:05") } func Time2Date(t time.Time) time.Time { year, month, day := t.Date() return time.Date(year, month, day, 0, 0, 0, 0, t.Location()) } func Time2DateStr(t time.Time) string { return t.Format("2006-01-02") } func Str2Time(timeStr string) time.Time { retVal, err := TryStr2Time(timeStr) if err != nil { baseapi.SugarLogger.Errorf("time.ParseInLocation failed, timeStr:%v, error:%v", timeStr, err) } return retVal } func TryStr2Time(timeStr string) (time.Time, error) { timeStr = strings.Replace(timeStr, "T", " ", 1) if strings.Index(timeStr, " ") == -1 { timeStr += " 00:00:00" } maxTimeStrLen := len("2018-05-03 09:18:40") if len(timeStr) > maxTimeStrLen { timeStr = timeStr[:maxTimeStrLen] } return time.ParseInLocation("2006-1-2 15:4:5", timeStr, time.Local) } func Str2TimeWithDefault(timeStr string, defValue time.Time) time.Time { retVal, err := TryStr2Time(timeStr) if err != nil { return defValue } return retVal } func IsTimeZero(timeValue time.Time) bool { return timeValue == DefaultTimeValue || timeValue == ZeroTimeValue } func HTTPBody2Values(data []byte, needDecode bool) (url.Values, error) { bodyStr := string(data) if needDecode { bodyStr1, err := url.QueryUnescape(bodyStr) if err != nil { baseapi.SugarLogger.Errorf("QueryUnescape error:%v, bodyStr:%v", err, bodyStr) return nil, err } bodyStr = bodyStr1 } result, err := url.ParseQuery(bodyStr) if err != nil { baseapi.SugarLogger.Errorf("ParseQuery error:%v, bodyStr:%v", err, bodyStr) return nil, err } return result, nil } func Params2Map(key1, value1 interface{}, kv ...interface{}) (retVal map[string]interface{}) { retVal = make(map[string]interface{}) retVal[key1.(string)] = value1 key := "" for index, v := range kv { if index%2 == 0 { key = v.(string) } else { retVal[key] = v } } return retVal } func URLValues2Map(values url.Values) (retVal map[string]interface{}) { retVal = make(map[string]interface{}) for k := range values { retVal[k], _ = url.QueryUnescape(values.Get(k)) } return retVal } func Map2URLValues(mapData map[string]interface{}) (retVal url.Values) { retVal = make(url.Values) for k, v := range mapData { retVal.Set(k, fmt.Sprint(v)) } return retVal } func MapKV2List(mapData map[string]interface{}) []map[string]interface{} { retVal := make([]map[string]interface{}, len(mapData)) index := 0 for _, v := range mapData { retVal[index] = v.(map[string]interface{}) index++ } return retVal } func MapKeys(mapData map[string]interface{}) (keys []string) { for k := range mapData { keys = append(keys, k) } return keys } func Format4Output(obj interface{}, isSingleLine bool) (retVal string) { retVal, ok := obj.(string) if !ok { var ( result []byte err error ) if isSingleLine { if result, err = json.Marshal(obj); err == nil { retVal = string(result) } } else { if result, err = json.MarshalIndent(obj, "", "\t"); err == nil { retVal = string(result) } } if err != nil { baseapi.SugarLogger.Infof("Format4Output Marshal:%v failed with error:%v", obj, err) retVal = fmt.Sprintf("%v", obj) } } return retVal } func Map2KeySlice(flagMap map[string]int) (keyList []string) { for k, v := range flagMap { if v != 0 { keyList = append(keyList, k) } } return keyList } // 合并map,相同字段以前面的优先,后来相同的字段忽略 func MergeMaps(firstMap map[string]interface{}, otherMaps ...map[string]interface{}) (retVal map[string]interface{}) { retVal = make(map[string]interface{}) allMaps := append([]map[string]interface{}{firstMap}, otherMaps...) mapCount := len(allMaps) for index := range allMaps { oneMap := allMaps[mapCount-index-1] for k, v := range oneMap { retVal[k] = v } } return retVal } func Struct2Map(obj interface{}, tagName string, isFlattenAnonymous bool) (mapData map[string]interface{}) { if tagName == "" { tagName = "json" } structsObj := structs.New(obj) structsObj.TagName = tagName structsObj.IsFlattenAnonymous = true return structsObj.Map() } func Struct2MapByJson(obj interface{}) (mapData map[string]interface{}) { return Struct2Map(obj, "", false) } func Struct2FlatMap(obj interface{}) map[string]interface{} { return Struct2Map(obj, "", true) } // !!! 此函数好像不支持struct是内嵌结构的 func Map2Struct(inObj interface{}, outObjAddr interface{}, weaklyTypedInput bool, tagName string) (err error) { if tagName == "" { tagName = "json" } decoder, _ := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ TagName: tagName, Result: outObjAddr, WeaklyTypedInput: weaklyTypedInput, }) return decoder.Decode(inObj) } func Map2StructByJson(inObj interface{}, outObjAddr interface{}, weaklyTypedInput bool) (err error) { return Map2Struct(inObj, outObjAddr, weaklyTypedInput, "") } func Int64Slice2String(intList []int64) (outList []string) { if len(intList) > 0 { outList = make([]string, len(intList)) for k, v := range intList { outList[k] = Int64ToStr(v) } } return outList } func StringSlice2Int64(intList []string) (outList []int64) { if len(intList) > 0 { outList = make([]int64, len(intList)) for k, v := range intList { outList[k] = Str2Int64WithDefault(v, 0) } } return outList } func StringSlice2Int(intList []string) (outList []int) { if len(intList) > 0 { outList = make([]int, len(intList)) for k, v := range intList { outList[k] = int(Str2Int64WithDefault(v, 0)) } } return outList } func IntSlice2Int64(intList []int) (outList []int64) { if len(intList) > 0 { outList = make([]int64, len(intList)) for k, v := range intList { outList[k] = int64(v) } } return outList }