diff --git a/filter.go b/filter.go index 4a71285..07233ec 100644 --- a/filter.go +++ b/filter.go @@ -10,12 +10,11 @@ package filter import ( "encoding/json" "fmt" - "git.zhangdeman.cn/zhangdeman/consts" - "git.zhangdeman.cn/zhangdeman/serialize" - "git.zhangdeman.cn/zhangdeman/wrapper" "reflect" "strings" + "git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack" + "git.zhangdeman.cn/zhangdeman/serialize" "github.com/tidwall/gjson" "github.com/tidwall/sjson" @@ -53,44 +52,22 @@ type filter struct { // Date : 11:59 2022/7/4 func (f *filter) Deal() error { var ( - err error - formatVal any + err error ) for _, rule := range f.filterRuleList { + if len(rule.TargetPath) == 0 { + // 未配置目标路径则, 目标路径和源路径保持一致 + rule.TargetPath = rule.SourcePath + } if f.IsArray(rule) { - // 对于list的处理 + // 对于list的处理, 展开层级, 并自动追加到f.filterRuleList 后面 if err = f.handleArray(rule); nil != err { return err } continue } - sourceResult := gjson.Get(f.sourceData, rule.SourcePath) - if formatVal, err = f.getValue(rule.DataType, sourceResult, rule.DefaultValue); nil != err { - return fmt.Errorf("%s = %v can not convert to %s : %s", rule.SourcePath, sourceResult.Value(), rule.DataType, err.Error()) - } - if reflect.TypeOf(formatVal).Kind() == reflect.Map { - // 获取的数据是map类型, 处理数据覆盖 - // eg : 配置如下两个规则 process.id(string) 、process(map[string]any) - // 若输入数据的process.id为int类型, 则格式化后的process.id必为 string, 应为 process.id 规则的控制更精细 - gjsonVal := gjson.Get(f.formatResult, rule.TargetPath) - if gjsonVal.Exists() && gjsonVal.IsObject() { - var ( - existRes = map[string]any{} - formatRes = map[string]any{} - ) - // 已存在, 且是对象 - _ = serialize.JSON.UnmarshalWithNumber([]byte(gjsonVal.String()), &existRes) - if err = serialize.JSON.Transition(formatVal, &formatRes); nil != err { - return errors.New("conflict data path config deal fail : " + err.Error()) - } - for k, v := range existRes { - formatRes[k] = v - } - formatVal = formatRes // 重新赋值 formatVal - } - } - if f.formatResult, err = sjson.Set(f.formatResult, rule.TargetPath, formatVal); nil != err { + if err = f.setResult(rule); nil != err { return err } } @@ -103,7 +80,7 @@ func (f *filter) Deal() error { // // Date : 17:48 2023/1/1 func (f *filter) IsArray(rule MapRule) bool { - return strings.Contains(rule.SourcePath, "[]") + return strings.Contains(rule.SourcePath, gjson_hack.ArrayIdxTpl) } // handleArray 处理数组(最复杂的场景) @@ -112,33 +89,71 @@ func (f *filter) IsArray(rule MapRule) bool { // // Date : 17:41 2023/1/1 func (f *filter) handleArray(rule MapRule) error { + // 对于list的处理, 展开层级, 并自动追加到f.filterRuleList 后面 var ( err error ) - sourcePathArray := strings.Split(rule.SourcePath, "[]") - for idx, item := range sourcePathArray { - sourcePathArray[idx] = strings.Trim(item, ".") + expendRes := &gjson_hack.ExpendArrayResult{ + PathList: make([]string, 0), + PathMap: map[string]string{}, } - mapPathArray := strings.Split(strings.TrimRight(rule.TargetPath, ".[]"), "[]") - for idx, item := range mapPathArray { - mapPathArray[idx] = strings.Trim(item, ".") + if err = gjson_hack.ExpandArrayPath(f.sourceData, rule.SourcePath, rule.TargetPath, expendRes); nil != err { + return err } - if len(sourcePathArray) != len(mapPathArray) { - if len(mapPathArray) != 1 { - return errors.New("map rule is invalid") - } - // 提取某一个list下的字段, 组成一个list - res := make([]string, 0) - if len(sourcePathArray[0]) == 0 { - f.getAllFinalData(&res, gjson.Parse(f.sourceData).Array(), sourcePathArray[1:]) - } else { - f.getAllFinalData(&res, gjson.Get(f.sourceData, sourcePathArray[0]).Array(), sourcePathArray[1:]) - } - if f.formatResult, err = sjson.Set(f.formatResult, mapPathArray[0], res); nil != err { + for _, itemPath := range expendRes.PathList { + if err = f.setResult(MapRule{ + SourcePath: itemPath, + TargetPath: expendRes.PathMap[itemPath], + Required: rule.Required, + DataType: rule.DataType, + DefaultValue: rule.DefaultValue, + }); nil != err { return err } - return nil + } + + return nil +} + +// setResult 设置结果 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 19:03 2024/11/30 +func (f *filter) setResult(rule MapRule) error { + var ( + err error + formatVal any + ) + + sourceResult := gjson.Get(f.sourceData, rule.SourcePath) + if formatVal, err = gjson_hack.Value(rule.DataType, sourceResult, rule.DefaultValue); nil != err { + return fmt.Errorf("%s = %v can not convert to %s : %s", rule.SourcePath, sourceResult.Value(), rule.DataType, err.Error()) + } + if reflect.TypeOf(formatVal).Kind() == reflect.Map { + // 获取的数据是map类型, 处理数据覆盖 + // eg : 配置如下两个规则 process.id(string) 、process(map[string]any) + // 若输入数据的process.id为int类型, 则格式化后的process.id必为 string, 应为 process.id 规则的控制更精细 + gjsonVal := gjson.Get(f.formatResult, rule.TargetPath) + if gjsonVal.Exists() && gjsonVal.IsObject() { + var ( + existRes = map[string]any{} + formatRes = map[string]any{} + ) + // 已存在, 且是对象 + _ = serialize.JSON.UnmarshalWithNumber([]byte(gjsonVal.String()), &existRes) + if err = serialize.JSON.Transition(formatVal, &formatRes); nil != err { + return errors.New("conflict data path config deal fail : " + err.Error()) + } + for k, v := range existRes { + formatRes[k] = v + } + formatVal = formatRes // 重新赋值 formatVal + } + } + if f.formatResult, err = sjson.Set(f.formatResult, rule.TargetPath, formatVal); nil != err { + return err } return nil } @@ -190,156 +205,3 @@ func (f *filter) Parse(receiver interface{}) error { } return json.Unmarshal(f.Byte(), receiver) } - -// getValue 获取值 -// -// Author : go_developer@163.com<白茶清欢> -// -// Date : 12:25 2022/7/4 -func (f *filter) getValue(dataType consts.DataType, sourceValue gjson.Result, defaultValue string) (any, error) { - sourceValueStr := defaultValue - if sourceValue.Exists() { - str := sourceValue.String() - if len(str) > 0 { - sourceValueStr = str - } - } - - strVal := wrapper.String(sourceValueStr) - - switch dataType { - case consts.DataTypeInt: - intVal := strVal.ToInt() - return intVal.Value, intVal.Err - case consts.DataTypeUint: - uintVal := strVal.ToUint64() - return uintVal.Value, uintVal.Err - case consts.DataTypeBool: - boolVal := strVal.ToBool() - return boolVal.Value, boolVal.Err - case consts.DataTypeFloat: - floatVal := strVal.ToFloat64() - return floatVal.Value, floatVal.Err - case consts.DataTypeString: - return strVal.Value(), nil - case consts.DataTypeAny: - if sourceValue.Exists() { - return sourceValue.Value(), nil - } - return defaultValue, nil - case consts.DataTypeSliceAny: - // 任意类型的list - sliceVal := strVal.ToAnySlice() - return sliceVal.Value, sliceVal.Err - case consts.DataTypeSliceInt, consts.DataTypeSliceIntWithChar: - // 任意类型的list - if strings.HasPrefix(strVal.Value(), "[") && strings.HasPrefix(strVal.Value(), "]") { - // 序列化之后的数组 - sliceVal := strVal.ToInt64Slice() - return sliceVal.Value, sliceVal.Err - } - // 分隔的数组 - sliceVal := strVal.ToInt64Slice(",") - return sliceVal.Value, sliceVal.Err - case consts.DataTypeSliceUint, consts.DataTypeSliceUintWithChar: - // 任意类型的list - if strings.HasPrefix(strVal.Value(), "[") && strings.HasPrefix(strVal.Value(), "]") { - // 序列化之后的数组 - sliceVal := strVal.ToUint64Slice() - return sliceVal.Value, sliceVal.Err - } - // 分隔的数组 - sliceVal := strVal.ToUint64Slice(",") - return sliceVal.Value, sliceVal.Err - case consts.DataTypeSliceFloat, consts.DataTypeSliceFloatWithChar: - // 任意类型的list - if strings.HasPrefix(strVal.Value(), "[") && strings.HasPrefix(strVal.Value(), "]") { - // 序列化之后的数组 - sliceVal := strVal.ToFloat64Slice() - return sliceVal.Value, sliceVal.Err - } - // 分隔的数组 - sliceVal := strVal.ToFloat64Slice(",") - return sliceVal.Value, sliceVal.Err - case consts.DataTypeSliceBool, consts.DataTypeSliceBoolWithChar: - // 任意类型的list - if strings.HasPrefix(strVal.Value(), "[") && strings.HasPrefix(strVal.Value(), "]") { - // 序列化之后的数组 - sliceVal := strVal.ToBoolSlice() - return sliceVal.Value, sliceVal.Err - } - // 分隔的数组 - sliceVal := strVal.ToBoolSlice(",") - return sliceVal.Value, sliceVal.Err - case consts.DataTypeSliceString, consts.DataTypeSliceStringWithChar: - // 任意类型的list - if strings.HasPrefix(strVal.Value(), "[") && strings.HasPrefix(strVal.Value(), "]") { - // 序列化之后的数组 - sliceVal := strVal.ToStringSlice() - return sliceVal.Value, sliceVal.Err - } - // 分隔的数组 - sliceVal := strVal.ToStringSlice(",") - return sliceVal.Value, sliceVal.Err - case consts.DataTypeSliceSlice, consts.DataTypeMapAnyAny: - return nil, errors.New(consts.DataTypeSliceSlice.String() + " : data type is not support") - case consts.DataTypeSliceMapStringAny: - if !sourceValue.IsArray() { - return nil, errors.New("data type is not array") - } - var res []map[string]any - err := strVal.ToStruct(&res) - return res, err - case consts.DataTypeMapStrInt: - if !sourceValue.IsObject() { - return nil, errors.New("data type is not object") - } - var res map[string]int64 - err := strVal.ToStruct(&res) - return res, err - case consts.DataTypeMapStrUint: - if !sourceValue.IsObject() { - return nil, errors.New("data type is not object") - } - var res map[string]uint64 - err := strVal.ToStruct(&res) - return res, err - case consts.DataTypeMapStrFloat: - if !sourceValue.IsObject() { - return nil, errors.New("data type is not object") - } - var res map[string]float64 - err := strVal.ToStruct(&res) - return res, err - case consts.DataTypeMapStrBool: - if !sourceValue.IsObject() { - return nil, errors.New("data type is not object") - } - var res map[string]bool - err := strVal.ToStruct(&res) - return res, err - case consts.DataTypeMapStrAny: - if !sourceValue.IsObject() { - return nil, errors.New("data type is not object") - } - var res map[string]any - err := strVal.ToStruct(&res) - return res, err - case consts.DataTypeMapStrStr: - if !sourceValue.IsObject() { - return nil, errors.New("data type is not object") - } - var res map[string]string - err := strVal.ToStruct(&res) - return res, err - case consts.DataTypeMapStrSlice: - if !sourceValue.IsObject() { - return nil, errors.New("data type is not object") - } - var res map[string][]any - err := strVal.ToStruct(&res) - return res, err - default: - return nil, errors.New(dataType.String() + " is not support!") - } -} diff --git a/gjson_hack/define.go b/gjson_hack/define.go index 855f4cf..577d477 100644 --- a/gjson_hack/define.go +++ b/gjson_hack/define.go @@ -40,5 +40,6 @@ const ( // // Date : 15:46 2024/11/29 type ExpendArrayResult struct { - PathList []string `json:"path_list"` // 路径列表 + PathList []string `json:"path_list"` // 路径列表 + PathMap map[string]string `json:"path_map"` // 数据源路径 => 目标路径的处理 } diff --git a/gjson_hack/error.go b/gjson_hack/error.go new file mode 100644 index 0000000..5e65ef8 --- /dev/null +++ b/gjson_hack/error.go @@ -0,0 +1,15 @@ +// Package gjson_hack ... +// +// Description : filter ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-11-30 19:14 +package gjson_hack + +import "errors" + +var ( + ErrDataIsNotObject = errors.New("data is not an object") + ErrDataIsNotArray = errors.New("data is not an array") +) diff --git a/gjson_hack/path.go b/gjson_hack/path.go index 3f06cee..2e7995a 100644 --- a/gjson_hack/path.go +++ b/gjson_hack/path.go @@ -10,8 +10,9 @@ package gjson_hack import ( "errors" "fmt" - "github.com/tidwall/gjson" "strings" + + "github.com/tidwall/gjson" ) // newDefaultPathOption 默认路径展开选项 @@ -131,22 +132,37 @@ func doExpandPath(gjsonResult gjson.Result, rootPath string, hasChildren bool, p // Author : go_developer@163.com<白茶清欢> // // Date : 11:13 2024/11/29 -func ExpandArrayPath(jsonStr string, pathConfig string, expendArrayResult *ExpendArrayResult) error { +func ExpandArrayPath(jsonStr string, pathConfig string, mapConfig string, expendArrayResult *ExpendArrayResult) error { if nil == expendArrayResult { return errors.New("expendArrayResult can not be nil") } if nil == expendArrayResult.PathList { expendArrayResult.PathList = make([]string, 0) } + if nil == expendArrayResult.PathMap { + expendArrayResult.PathMap = make(map[string]string) + } + if len(mapConfig) == 0 { + mapConfig = pathConfig + } if !strings.Contains(pathConfig, ArrayIdxTpl) { // 不是数组模板配置, 无需展开 expendArrayResult.PathList = append(expendArrayResult.PathList, pathConfig) + expendArrayResult.PathMap[pathConfig] = mapConfig return nil } + mapConfigArr := strings.Split(mapConfig, ArrayIdxTpl) + mapConfigArr[0] = strings.TrimSuffix(mapConfigArr[0], ".") + mapSuffixPathTpl := strings.TrimPrefix(strings.Join(mapConfigArr[1:], ArrayIdxTpl), ".") pathConfigArr := strings.Split(pathConfig, ArrayIdxTpl) pathConfigArr[0] = strings.TrimSuffix(pathConfigArr[0], ".") suffixPathTpl := strings.TrimPrefix(strings.Join(pathConfigArr[1:], ArrayIdxTpl), ".") + + if len(mapConfigArr) != len(pathConfigArr) { + return errors.New("mapConfig depth not equal pathConfig deep") + } + valueResult := gjson.Parse(jsonStr).Get(pathConfigArr[0]) if !valueResult.Exists() { // 路径不存在, 无需设置具体值 @@ -155,14 +171,74 @@ func ExpandArrayPath(jsonStr string, pathConfig string, expendArrayResult *Expen if !valueResult.IsArray() { // 不是数组,不要继续再向后展开了 expendArrayResult.PathList = append(expendArrayResult.PathList, pathConfigArr[0]) + expendArrayResult.PathMap[pathConfigArr[0]] = mapConfigArr[0] return nil } // 继续展开子项 for idx, _ := range valueResult.Array() { idxStr := fmt.Sprintf("%v", idx) - if err := ExpandArrayPath(jsonStr, pathConfigArr[0]+"."+idxStr+"."+suffixPathTpl, expendArrayResult); nil != err { + if err := ExpandArrayPath(jsonStr, pathConfigArr[0]+"."+idxStr+"."+suffixPathTpl, mapConfigArr[0]+"."+idxStr+"."+mapSuffixPathTpl, expendArrayResult); nil != err { return err } } return nil } + +// IsObject 判断是否是对象, 兼容序列化之后的对象 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 18:04 2024/12/1 +func IsObject(gjsonResult gjson.Result) bool { + return gjsonResult.IsObject() || gjson.Parse(gjsonResult.String()).IsObject() +} + +// IsArray 判断是否为数组 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 18:05 2024/12/1 +func IsArray(gjsonResult gjson.Result) bool { + return gjsonResult.IsArray() || gjson.Parse(gjsonResult.String()).IsArray() +} + +// Object 兼容序列化之后的对象 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 18:09 2024/12/1 +func Object(gjsonResult gjson.Result) gjson.Result { + res := gjson.Parse(gjsonResult.String()) + if res.IsObject() { + return res + } + return gjsonResult +} + +// Array ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 18:09 2024/12/1 +func Array(gjsonResult gjson.Result) gjson.Result { + res := gjson.Parse(gjsonResult.String()) + if res.IsArray() { + return res + } + return gjsonResult +} + +// Result ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 18:12 2024/12/1 +func Result(gjsonResult gjson.Result) gjson.Result { + if IsObject(gjsonResult) { + return gjsonResult + } + if IsArray(gjsonResult) { + return Array(gjsonResult) + } + return gjsonResult +} diff --git a/gjson_hack/path_test.go b/gjson_hack/path_test.go index 6b2409b..1848b11 100644 --- a/gjson_hack/path_test.go +++ b/gjson_hack/path_test.go @@ -10,8 +10,11 @@ package gjson_hack import ( "encoding/json" "fmt" - "github.com/tidwall/gjson" "testing" + + "github.com/tidwall/sjson" + + "github.com/tidwall/gjson" ) func TestPath(t *testing.T) { @@ -162,8 +165,17 @@ func TestExpandArrayPath(t *testing.T) { } byteData, _ := json.Marshal(mapData) jsonStr := string(byteData) - // fmt.Println(jsonStr) - var pathExpendRes = &ExpendArrayResult{PathList: nil} - ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.age", pathExpendRes) - fmt.Println(pathExpendRes) + + var pathExpendRes = &ExpendArrayResult{ + PathList: nil, + PathMap: nil, + } + ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.age", "a.{{idx}}.{{idx}}.b", pathExpendRes) + ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.name", "e.{{idx}}.{{idx}}.c", pathExpendRes) + ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.sex", "f.{{idx}}.{{idx}}.c", pathExpendRes) + res := "" + for _, item := range pathExpendRes.PathList { + res, _ = sjson.Set(res, pathExpendRes.PathMap[item], gjson.Get(jsonStr, item).Value()) + } + fmt.Println(res) } diff --git a/gjson_hack/precision.go b/gjson_hack/precision.go index 1877737..328c07b 100644 --- a/gjson_hack/precision.go +++ b/gjson_hack/precision.go @@ -9,8 +9,12 @@ 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) @@ -69,3 +73,348 @@ func Float64(gjsonResult gjson.Result) (float64, error) { } 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 +} + +// MapAnyAny ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 17:48 2024/12/1 +func MapAnyAny(sourceValue gjson.Result) (map[string]any, error) { + if !sourceValue.IsObject() { + return nil, ErrDataIsNotObject + } + res := make(map[string]any) + sourceValue.ForEach(func(key, value gjson.Result) bool { + res[key.String()] = value + return true + }) + return res, nil +} + +// 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() { + return MapAnyAny(sourceValue) + } + if sourceValue.IsArray() { + return SliceAny(sourceValue) + } + 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 { + // 指针数据类型, 转换为普通数据类型处理 + dataType = consts.DataType(strings.TrimLeft(dataType.String(), "*")) + 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 +} + +// SliceAny ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 17:53 2024/12/1 +func SliceAny(gjsonResult gjson.Result) ([]any, 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).ToAnySlice() + return sliceVal.Value, sliceVal.Err + } + // 分隔的数组 + sliceVal := wrapper.String(strVal).ToAnySlice(",") + return sliceVal.Value, sliceVal.Err +} + +// 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 +} + +// SliceSlice ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 17:44 2024/12/1 +func SliceSlice(gjsonResult gjson.Result) ([][]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 [][]any + if err := serialize.JSON.UnmarshalWithNumber([]byte(strVal), &res); nil != err { + return nil, err + } + return res, nil +} + +// MapStrAny 获取任意map类型的结果 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 14:26 2024/12/2 +func MapStrAny[T string | int64 | uint64 | bool | float64 | []any | map[string]any | any](gjsonResult gjson.Result) (map[string]T, error) { + if !gjsonResult.IsObject() { + return nil, ErrDataIsNotObject + } + var res map[string]T + if err := serialize.JSON.UnmarshalWithNumber([]byte(gjsonResult.String()), &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 + } + // 归一化处理对象、数组等 + sourceValue = Result(sourceValue) + 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: + return SliceSlice(sourceValue) + case consts.DataTypeMapAnyAny: + return MapAnyAny(sourceValue) + case consts.DataTypeSliceMapStringAny: + return SliceMapStringAny(sourceValue) + case consts.DataTypeMapStrInt: + return MapStrAny[int64](sourceValue) + case consts.DataTypeMapStrUint: + return MapStrAny[uint64](sourceValue) + case consts.DataTypeMapStrFloat: + return MapStrAny[float64](sourceValue) + case consts.DataTypeMapStrBool: + return MapStrAny[bool](sourceValue) + case consts.DataTypeMapStrAny: + return MapStrAny[any](sourceValue) + case consts.DataTypeMapStrStr: + return MapStrAny[string](sourceValue) + case consts.DataTypeMapStrSlice: + return MapStrAny[[]any](sourceValue) + default: + return nil, errors.New("data_type = `" + dataType.String() + "` is not support!") + } +}