376 lines
9.9 KiB
Go
376 lines
9.9 KiB
Go
// Package gjson_hack 精确地类型转换
|
|
//
|
|
// Description : gjson_hack ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 2024-11-27 10:47
|
|
package gjson_hack
|
|
|
|
import (
|
|
"errors"
|
|
"git.zhangdeman.cn/zhangdeman/consts"
|
|
"git.zhangdeman.cn/zhangdeman/serialize"
|
|
"git.zhangdeman.cn/zhangdeman/util"
|
|
"git.zhangdeman.cn/zhangdeman/wrapper"
|
|
"github.com/tidwall/gjson"
|
|
"strings"
|
|
)
|
|
|
|
// Number 结果转换为数字(int64 / uint64 / float64)
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 10:57 2024/11/27
|
|
func Number[T int64 | uint64 | float64](gjsonResult gjson.Result, numberReceiver *T) error {
|
|
if !gjsonResult.Exists() {
|
|
return errors.New("gjson result not found")
|
|
}
|
|
if gjsonResult.Type != gjson.Number {
|
|
return errors.New(gjsonResult.String() + " : value not a number")
|
|
}
|
|
if err := util.ConvertAssign(numberReceiver, gjsonResult.String()); nil != err {
|
|
return errors.New(gjsonResult.String() + " : convert to num fail -> " + err.Error())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Int 转int
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 11:19 2024/11/27
|
|
func Int(gjsonResult gjson.Result) (int64, error) {
|
|
var intResult int64
|
|
if err := Number(gjsonResult, &intResult); nil != err {
|
|
return 0, err
|
|
}
|
|
return intResult, nil
|
|
}
|
|
|
|
// Uint 转为uint64
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 11:21 2024/11/27
|
|
func Uint(gjsonResult gjson.Result) (uint64, error) {
|
|
var uintResult uint64
|
|
if err := Number(gjsonResult, &uintResult); nil != err {
|
|
return 0, err
|
|
}
|
|
return uintResult, nil
|
|
}
|
|
|
|
// Float64 转为float64
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 11:24 2024/11/27
|
|
func Float64(gjsonResult gjson.Result) (float64, error) {
|
|
var float64Result float64
|
|
if err := Number(gjsonResult, &float64Result); nil != err {
|
|
return 0, err
|
|
}
|
|
return float64Result, nil
|
|
}
|
|
|
|
// String 获取字符串值
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 10:55 2024/12/1
|
|
func String(sourceValue gjson.Result, defaultValue string) string {
|
|
sourceValueStr := defaultValue
|
|
if sourceValue.Exists() {
|
|
str := sourceValue.String()
|
|
if len(str) > 0 {
|
|
sourceValueStr = str
|
|
}
|
|
}
|
|
return sourceValueStr
|
|
}
|
|
|
|
// Any 获取任意类型的值
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 11:00 2024/12/1
|
|
func Any(sourceValue gjson.Result) (any, error) {
|
|
if !sourceValue.Exists() {
|
|
return nil, nil
|
|
}
|
|
// 可能存在精度丢失, 原因 : gjson.Value 内置的转换, int64 超过一定大小会存在丢失精度问题
|
|
if sourceValue.Num > 0 || sourceValue.Num < 0 {
|
|
// 说明是数字
|
|
var res float64
|
|
if err := util.ConvertAssign(&res, sourceValue.String()); nil != err {
|
|
return nil, err
|
|
}
|
|
return res, nil
|
|
}
|
|
if sourceValue.IsObject() {
|
|
// 对象不管什么类型的key, 统一转成 map[string]any
|
|
res := make(map[string]any)
|
|
sourceValue.ForEach(func(k, v gjson.Result) bool {
|
|
res[k.String()] = v
|
|
return true
|
|
})
|
|
}
|
|
return sourceValue.Value(), nil
|
|
|
|
}
|
|
|
|
// getRealDataType ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 14:28 2024/12/1
|
|
func getRealDataType(dataType consts.DataType, sourceValue gjson.Result) consts.DataType {
|
|
if dataType == consts.DataTypeAny {
|
|
if sourceValue.IsObject() {
|
|
dataType = consts.DataTypeMapAnyAny
|
|
} else if sourceValue.IsArray() {
|
|
dataType = consts.DataTypeSliceAny
|
|
} else {
|
|
if sourceValue.Num != 0 {
|
|
dataType = consts.DataTypeFloat
|
|
}
|
|
}
|
|
}
|
|
return dataType
|
|
}
|
|
|
|
// SliceInt 获取int list
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 14:43 2024/12/1
|
|
func SliceInt(gjsonResult gjson.Result) ([]int64, error) {
|
|
if gjsonResult.Value() == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
strVal := strings.TrimSpace(gjsonResult.String())
|
|
// 任意类型的list
|
|
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
|
// 序列化之后的数组
|
|
sliceVal := wrapper.String(strVal).ToInt64Slice()
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
// 分隔的数组
|
|
sliceVal := wrapper.String(strVal).ToInt64Slice(",")
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
|
|
// SliceUint ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 14:58 2024/12/1
|
|
func SliceUint(gjsonResult gjson.Result) ([]uint64, error) {
|
|
if gjsonResult.Value() == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
strVal := strings.TrimSpace(gjsonResult.String())
|
|
// 任意类型的list
|
|
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
|
// 序列化之后的数组
|
|
sliceVal := wrapper.String(strVal).ToUint64Slice()
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
// 分隔的数组
|
|
sliceVal := wrapper.String(strVal).ToUint64Slice(",")
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
|
|
// SliceFloat ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 14:59 2024/12/1
|
|
func SliceFloat(gjsonResult gjson.Result) ([]float64, error) {
|
|
if gjsonResult.Value() == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
strVal := strings.TrimSpace(gjsonResult.String())
|
|
// 任意类型的list
|
|
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
|
// 序列化之后的数组
|
|
sliceVal := wrapper.String(strVal).ToFloat64Slice()
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
// 分隔的数组
|
|
sliceVal := wrapper.String(strVal).ToFloat64Slice(",")
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
|
|
// SliceBool ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 15:00 2024/12/1
|
|
func SliceBool(gjsonResult gjson.Result) ([]bool, error) {
|
|
if gjsonResult.Value() == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
strVal := strings.TrimSpace(gjsonResult.String())
|
|
// 任意类型的list
|
|
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
|
// 序列化之后的数组
|
|
sliceVal := wrapper.String(strVal).ToBoolSlice()
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
// 分隔的数组
|
|
sliceVal := wrapper.String(strVal).ToBoolSlice(",")
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
|
|
// SliceString ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 15:03 2024/12/1
|
|
func SliceString(gjsonResult gjson.Result) ([]string, error) {
|
|
if gjsonResult.Value() == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
strVal := strings.TrimSpace(gjsonResult.String())
|
|
// 任意类型的list
|
|
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
|
// 序列化之后的数组
|
|
sliceVal := wrapper.String(strVal).ToStringSlice()
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
// 分隔的数组
|
|
sliceVal := wrapper.String(strVal).ToStringSlice(",")
|
|
return sliceVal.Value, sliceVal.Err
|
|
}
|
|
|
|
// SliceMapStringAny ...
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 15:41 2024/12/1
|
|
func SliceMapStringAny(gjsonResult gjson.Result) ([]map[string]any, error) {
|
|
if gjsonResult.Value() == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
strVal := strings.TrimSpace(gjsonResult.String())
|
|
// 任意类型的list
|
|
if !strings.HasPrefix(strVal, "[") || !strings.HasSuffix(strVal, "]") {
|
|
return nil, ErrDataIsNotArray
|
|
}
|
|
var res []map[string]any
|
|
if err := serialize.JSON.UnmarshalWithNumber([]byte(strVal), &res); nil != err {
|
|
return nil, err
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
// Value 获取指定的值
|
|
//
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
//
|
|
// Date : 10:52 2024/12/1
|
|
func Value(dataType consts.DataType, sourceValue gjson.Result, defaultValue any) (any, error) {
|
|
if !sourceValue.Exists() {
|
|
return defaultValue, nil
|
|
}
|
|
dataType = getRealDataType(dataType, sourceValue)
|
|
strVal := wrapper.String(sourceValue.String())
|
|
switch dataType {
|
|
case consts.DataTypeInt:
|
|
return Int(sourceValue)
|
|
case consts.DataTypeUint:
|
|
return Uint(sourceValue)
|
|
case consts.DataTypeFloat:
|
|
return Float64(sourceValue)
|
|
case consts.DataTypeBool:
|
|
boolVal := strVal.ToBool()
|
|
return boolVal.Value, boolVal.Err
|
|
case consts.DataTypeString:
|
|
return sourceValue.String(), nil
|
|
case consts.DataTypeAny:
|
|
return sourceValue.Value(), nil
|
|
case consts.DataTypeSliceAny:
|
|
// 任意类型的list
|
|
sliceVal := strVal.ToAnySlice()
|
|
return sliceVal.Value, sliceVal.Err
|
|
case consts.DataTypeSliceInt, consts.DataTypeSliceIntWithChar:
|
|
// 任意类型的list
|
|
return SliceInt(sourceValue)
|
|
case consts.DataTypeSliceUint, consts.DataTypeSliceUintWithChar:
|
|
// 任意类型的list
|
|
return SliceUint(sourceValue)
|
|
case consts.DataTypeSliceFloat, consts.DataTypeSliceFloatWithChar:
|
|
// 任意类型的list
|
|
return SliceFloat(sourceValue)
|
|
case consts.DataTypeSliceBool, consts.DataTypeSliceBoolWithChar:
|
|
// 任意类型的list
|
|
return SliceBool(sourceValue)
|
|
case consts.DataTypeSliceString, consts.DataTypeSliceStringWithChar:
|
|
// 任意类型的list
|
|
return SliceString(sourceValue)
|
|
case consts.DataTypeSliceSlice, consts.DataTypeMapAnyAny:
|
|
return nil, errors.New(consts.DataTypeSliceSlice.String() + " : data type is not support")
|
|
case consts.DataTypeSliceMapStringAny:
|
|
return SliceMapStringAny(sourceValue)
|
|
case consts.DataTypeMapStrInt:
|
|
if !sourceValue.IsObject() {
|
|
return nil, ErrDataIsNotObject
|
|
}
|
|
var res map[string]int64
|
|
err := strVal.ToStruct(&res)
|
|
return res, err
|
|
case consts.DataTypeMapStrUint:
|
|
if !sourceValue.IsObject() {
|
|
return nil, ErrDataIsNotObject
|
|
}
|
|
var res map[string]uint64
|
|
err := strVal.ToStruct(&res)
|
|
return res, err
|
|
case consts.DataTypeMapStrFloat:
|
|
if !sourceValue.IsObject() {
|
|
return nil, ErrDataIsNotObject
|
|
}
|
|
var res map[string]float64
|
|
err := strVal.ToStruct(&res)
|
|
return res, err
|
|
case consts.DataTypeMapStrBool:
|
|
if !sourceValue.IsObject() {
|
|
return nil, ErrDataIsNotObject
|
|
}
|
|
var res map[string]bool
|
|
err := strVal.ToStruct(&res)
|
|
return res, err
|
|
case consts.DataTypeMapStrAny:
|
|
if !sourceValue.IsObject() {
|
|
return nil, ErrDataIsNotObject
|
|
}
|
|
var res map[string]any
|
|
err := strVal.ToStruct(&res)
|
|
return res, err
|
|
case consts.DataTypeMapStrStr:
|
|
if !sourceValue.IsObject() {
|
|
return nil, ErrDataIsNotObject
|
|
}
|
|
var res map[string]string
|
|
err := strVal.ToStruct(&res)
|
|
return res, err
|
|
case consts.DataTypeMapStrSlice:
|
|
if !sourceValue.IsObject() {
|
|
return nil, ErrDataIsNotObject
|
|
}
|
|
var res map[string][]any
|
|
err := strVal.ToStruct(&res)
|
|
return res, err
|
|
default:
|
|
return nil, errors.New("`" + dataType.String() + "` is not support!")
|
|
}
|
|
}
|