package common import ( "bytes" "encoding/json" "errors" "math" "strconv" "strings" "time" ) // 仅限于hotime.Slice func ObjToMap(obj interface{}, e ...*Error) Map { var err error var v Map if obj == nil { v = nil err = errors.New("没有合适的转换对象!") } else { switch val := obj.(type) { case Map: v = val case map[string]interface{}: v = Map(val) case string: result, e2 := JsonToObj(val) if e2 != nil { err = errors.New("没有合适的转换对象!" + e2.Error()) v = nil } else if m, ok := result.(map[string]interface{}); ok { v = m } else { err = errors.New("没有合适的转换对象!") v = nil } default: var data []byte data, err = json.Marshal(obj) if err != nil { err = errors.New("没有合适的转换对象!" + err.Error()) v = nil break } result, e2 := JsonToObj(string(data)) if e2 != nil { err = errors.New("没有合适的转换对象!" + e2.Error()) v = nil } else if m, ok := result.(map[string]interface{}); ok { v = m } else { err = errors.New("没有合适的转换对象!") v = nil } } } if len(e) != 0 { e[0].SetError(err) } return v } func ObjToMapArray(obj interface{}, e ...*Error) []Map { s := ObjToSlice(obj, e...) res := make([]Map, 0, len(s)) for i := 0; i < len(s); i++ { res = append(res, s.GetMap(i)) } return res } // 仅限于hotime.Slice func ObjToSlice(obj interface{}, e ...*Error) Slice { var err error var v Slice if obj == nil { v = nil err = errors.New("没有合适的转换对象!") } else { switch val := obj.(type) { case Slice: v = val case []interface{}: v = Slice(val) case []string: v = make(Slice, len(val)) for i, s := range val { v[i] = s } case string: result, e2 := JsonToObj(val) if e2 != nil { err = e2 } else if s, ok := result.([]interface{}); ok { v = s } else { err = errors.New("没有合适的转换对象!") } default: var data []byte data, err = json.Marshal(obj) if err != nil { break } result, e2 := JsonToObj(string(data)) if e2 != nil { err = e2 } else if s, ok := result.([]interface{}); ok { v = s } else { err = errors.New("没有合适的转换对象!") } } } if len(e) != 0 { e[0].SetError(err) } return v } func ObjToTime(obj interface{}, e ...*Error) *time.Time { tInt := ObjToInt64(obj) //字符串类型,只支持标准mysql datetime格式 if tInt == 0 { tStr := ObjToStr(obj) // 先分离日期和时间部分,再对日期各段补零,避免时间中的数字被误处理 datePart := tStr timePart := "" if idx := strings.Index(tStr, " "); idx > 0 { datePart = tStr[:idx] timePart = tStr[idx:] // 含前导空格 } dateSegs := strings.Split(datePart, "-") for i, seg := range dateSegs { if seg == "" { continue } if len(seg) == 1 { dateSegs[i] = "0" + seg } } tStr = strings.Join(dateSegs, "-") + timePart if len(tStr) > 18 { t, e := time.Parse("2006-01-02 15:04:05", tStr) if e == nil { return &t } } else if len(tStr) > 15 { t, e := time.Parse("2006-01-02 15:04", tStr) if e == nil { return &t } } else if len(tStr) > 12 { t, e := time.Parse("2006-01-02 15", tStr) if e == nil { return &t } } else if len(tStr) > 9 { t, e := time.Parse("2006-01-02", tStr) if e == nil { return &t } } else if len(tStr) > 6 { t, e := time.Parse("2006-01", tStr) if e == nil { return &t } } } // 缓存字符串,避免重复调用 tIntStr := ObjToStr(tInt) tIntLen := len(tIntStr) //纳秒级别 if tIntLen > 16 { t := time.UnixMicro(tInt / 1000) return &t //微秒级别 } else if tIntLen > 13 { t := time.UnixMicro(tInt) return &t //毫秒级别 } else if tIntLen > 10 { t := time.UnixMilli(tInt) return &t //秒级别 } else if tIntLen > 9 { t := time.Unix(tInt, 0) return &t } else if tIntLen > 3 { t, e := time.Parse("2006", tIntStr) if e == nil { return &t } } return nil } func ObjToFloat64(obj interface{}, e ...*Error) float64 { var err error v := float64(0) if obj == nil { err = errors.New("没有合适的转换对象!") } else { switch val := obj.(type) { case int: v = float64(val) case int8: v = float64(val) case int16: v = float64(val) case int32: v = float64(val) case int64: v = float64(val) case uint: v = float64(val) case uint8: v = float64(val) case uint16: v = float64(val) case uint32: v = float64(val) case uint64: v = float64(val) case bool: if val { v = 1 } case string: value, e2 := strconv.ParseFloat(val, 64) if e2 != nil { err = e2 } else { v = value } case float64: v = val case float32: // 通过 string 中转避免 float32→float64 精度膨胀(如 float32(1.2) 直接转得 1.200000047...) v, _ = strconv.ParseFloat(strconv.FormatFloat(float64(val), 'f', -1, 32), 64) case []byte: // 数据库 driver 有时以 []byte 返回数值字符串 value, e2 := strconv.ParseFloat(string(val), 64) if e2 != nil { err = e2 } else { v = value } default: err = errors.New("没有合适的转换对象!") } } if math.IsNaN(v) { err = errors.New("float64 is NaN") v = 0 } if math.IsInf(v, 0) { err = errors.New("float64 is Inf") v = 0 } if len(e) != 0 { e[0].SetError(err) } return v } // ObjToRoundFloat64 将 obj 转为 float64 后四舍五入到 precision 位小数。 // precision < 0 时不做舍入,直接返回原始 float64。 func ObjToRoundFloat64(obj interface{}, precision int, e ...*Error) float64 { f := ObjToFloat64(obj, e...) if precision < 0 { return f } pow := math.Pow10(precision) return math.Round(f*pow) / pow } // 向上取整 func ObjToCeilInt64(obj interface{}, e ...*Error) int64 { f := ObjToCeilFloat64(obj, e...) return int64(f) } // 向上取整 func ObjToCeilFloat64(obj interface{}, e ...*Error) float64 { f := ObjToFloat64(obj, e...) return math.Ceil(f) } // 向上取整 func ObjToCeilInt(obj interface{}, e ...*Error) int { f := ObjToCeilFloat64(obj, e...) return ObjToInt(f) } func ObjToInt64(obj interface{}, e ...*Error) int64 { var err error v := int64(0) if obj == nil { err = errors.New("没有合适的转换对象!") } else { switch val := obj.(type) { case int: v = int64(val) case int8: v = int64(val) case int16: v = int64(val) case int32: v = int64(val) case int64: v = val case uint: v = int64(val) case uint8: v = int64(val) case uint16: v = int64(val) case uint32: v = int64(val) case uint64: v = int64(val) case bool: if val { v = 1 } case string: value, e2 := StrToInt(val) if e2 != nil { // fallback:处理 "1.20" 这类带小数点的整数字符串 if fv, fe := strconv.ParseFloat(val, 64); fe == nil { v = int64(fv) } else { err = e2 } } else { v = int64(value) } case []byte: // 数据库 driver 有时以 []byte 返回整数字符串 value, e2 := StrToInt(string(val)) if e2 != nil { // fallback:处理 "1.20" 这类带小数点的整数字符串 if fv, fe := strconv.ParseFloat(string(val), 64); fe == nil { v = int64(fv) } else { err = e2 } } else { v = int64(value) } case float64: v = int64(val) case float32: v = int64(val) default: err = errors.New("没有合适的转换对象!") } } if len(e) != 0 { e[0].SetError(err) } return v } func ObjToInt(obj interface{}, e ...*Error) int { v := ObjToInt64(obj, e...) return int(v) } func ObjToBool(obj interface{}, e ...*Error) bool { var err error v := false if obj == nil { err = errors.New("没有合适的转换对象!") } else { switch val := obj.(type) { case bool: v = val default: var intErr Error toInt := ObjToInt(obj, &intErr) if intErr.GetError() != nil { err = errors.New("没有合适的转换对象!") } else if toInt != 0 { v = true } } } if len(e) != 0 { e[0].SetError(err) } return v } func ObjToStr(obj interface{}) string { str := "" if obj == nil { return str } switch val := obj.(type) { case int: str = strconv.Itoa(val) case int8: str = strconv.Itoa(int(val)) case int16: str = strconv.Itoa(int(val)) case int32: str = strconv.Itoa(int(val)) case uint8: str = strconv.Itoa(int(val)) case uint16: str = strconv.Itoa(int(val)) case uint32: str = strconv.FormatUint(uint64(val), 10) case uint64: str = strconv.FormatUint(val, 10) case int64: str = strconv.FormatInt(val, 10) case []byte: str = string(val) case string: str = val case float64: str = strconv.FormatFloat(val, 'f', -1, 64) case float32: str = strconv.FormatFloat(float64(val), 'f', -1, 32) case bool: str = strconv.FormatBool(val) case time.Time: // DM8等数据库驱动直接返回time.Time,格式化为MySQL兼容的字符串 str = val.Format("2006-01-02 15:04:05") default: strbte, err := json.MarshalIndent(obj, "", "\t") if err == nil { str = string(strbte) } } return str } // JsonToObj 将 JSON 字符串反序列化为 interface{},保留数字原始类型。 // 标准 json.Unmarshal 会把所有 JSON 数字变成 float64,本函数保留整数为 int64、小数为 float64。 // // JsonToObj(`{"id":2,"price":1.20}`) → map{"id": int64(2), "price": float64(1.2)} // JsonToObj(`[1, 2.5, "a"]`) → []interface{}{int64(1), float64(2.5), "a"} func JsonToObj(jsonStr string) (interface{}, error) { dec := json.NewDecoder(bytes.NewReader([]byte(jsonStr))) dec.UseNumber() var result interface{} if err := dec.Decode(&result); err != nil { return nil, err } return fixJsonNumbers(result), nil } // fixJsonNumbers 递归将 json.Number 转为 int64 或 float64 func fixJsonNumbers(v interface{}) interface{} { switch val := v.(type) { case json.Number: if n, err := val.Int64(); err == nil { return n } if f, err := val.Float64(); err == nil { return f } return string(val) case map[string]interface{}: for k, item := range val { val[k] = fixJsonNumbers(item) } return val case []interface{}: for i, item := range val { val[i] = fixJsonNumbers(item) } return val default: return val } } // 转换为Map func StrToMap(s string) Map { data := Map{} data.JsonToMap(s) return data } // 转换为Slice func StrToSlice(s string) Slice { return ObjToSlice(s) } // 字符串数组: a1,a2,a3转["a1","a2","a3"] func StrArrayToJsonStr(a string) string { if len(a) > 2 { if a[0] == ',' { a = Substr(a, 1, len(a)-1) } if a[len(a)-1] == ',' { a = Substr(a, 0, len(a)-1) } a = `[` + a + `]` } else { a = "[]" } return a } // 字符串数组: ["a1","a2","a3"]转,a1,a2,a3, func JsonStrToStrArray(a string) string { if len(a) != 0 { a = Substr(a, 1, len(a)-2) } return "," + a + "," } // 字符串转int func StrToInt(s string) (int, error) { i, err := strconv.Atoi(s) return i, err }