Files
hotime/common/objtoobj.go
T
hoteas fab7931d3c refactor(app): 优化 URL 处理和 JSON 解析逻辑
- 更新应用程序处理程序中的 URL 赋值逻辑,确保静态文件使用原始路径
- 修改缓存数据库的 JSON 解析方法,使用 JsonToObj 函数替代 json.Unmarshal,提升代码可读性和性能
- 在 Map 和 Slice 类型中新增获取四舍五入浮点数的方法,增强数据处理能力
- 在 Obj 类型中添加四舍五入功能,支持精度控制
- 改进数据库查询结果的处理逻辑,确保数据类型的准确性和一致性
- 优化日志格式设置,增强日志信息的可读性
2026-03-10 23:44:41 +08:00

484 lines
9.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 int64:
v = float64(val)
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 int64:
v = val
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 uint8:
str = strconv.Itoa(int(val))
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)
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
}