diff --git a/define.go b/define.go index a80d083..e121323 100644 --- a/define.go +++ b/define.go @@ -14,7 +14,7 @@ package filter // Date : 12:21 2022/7/4 type MapRule struct { SourcePath string `json:"source_path"` // 原路径 - MapPath string `json:"map_path"` // 映射路径 + TargetPath string `json:"target_path"` // 目标路径路径 Required bool `json:"required"` // 必须存在 DataType string `json:"data_type"` // 数据类型 DefaultValue string `json:"default_value"` // 默认值, 以字符串传入, 会转换成 DataType diff --git a/filter.go b/filter.go index dcd4a81..78dd7ff 100644 --- a/filter.go +++ b/filter.go @@ -11,7 +11,9 @@ import ( "encoding/json" "fmt" "git.zhangdeman.cn/zhangdeman/consts" + "git.zhangdeman.cn/zhangdeman/serialize" "git.zhangdeman.cn/zhangdeman/wrapper" + "reflect" "strings" "github.com/tidwall/gjson" @@ -52,7 +54,7 @@ type filter struct { func (f *filter) Deal() error { var ( err error - formatVal interface{} + formatVal any ) for _, rule := range f.filterRuleList { @@ -67,7 +69,28 @@ func (f *filter) Deal() error { 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 f.formatResult, err = sjson.Set(f.formatResult, rule.MapPath, formatVal); nil != err { + 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 } } @@ -97,7 +120,7 @@ func (f *filter) handleArray(rule MapRule) error { for idx, item := range sourcePathArray { sourcePathArray[idx] = strings.Trim(item, ".") } - mapPathArray := strings.Split(strings.TrimRight(rule.MapPath, ".[]"), "[]") + mapPathArray := strings.Split(strings.TrimRight(rule.TargetPath, ".[]"), "[]") for idx, item := range mapPathArray { mapPathArray[idx] = strings.Trim(item, ".") } @@ -173,7 +196,7 @@ func (f *filter) Parse(receiver interface{}) error { // Author : go_developer@163.com<白茶清欢> // // Date : 12:25 2022/7/4 -func (f *filter) getValue(dataType string, sourceValue gjson.Result, defaultValue string) (interface{}, error) { +func (f *filter) getValue(dataType string, sourceValue gjson.Result, defaultValue string) (any, error) { sourceValueStr := defaultValue if sourceValue.Exists() { str := sourceValue.String() @@ -208,10 +231,114 @@ func (f *filter) getValue(dataType string, sourceValue gjson.Result, defaultValu // 任意类型的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 + " : 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: - // object - objectVal := strVal.ToObject() - return objectVal.Value, objectVal.Err + 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 + " is not support!") } diff --git a/filter_test.go b/filter_test.go index ae15bf8..7c8f263 100644 --- a/filter_test.go +++ b/filter_test.go @@ -8,6 +8,7 @@ package filter import ( + "encoding/json" "fmt" "testing" @@ -37,35 +38,35 @@ func TestNewFilter(t *testing.T) { filterRuleList := []MapRule{ { SourcePath: "base.name", - MapPath: "user_name", + TargetPath: "user_name", Required: true, DataType: "string", DefaultValue: "", }, { SourcePath: "base.age", - MapPath: "user_age", + TargetPath: "user_age", Required: true, DataType: "int", DefaultValue: "", }, { SourcePath: "base.height", - MapPath: "user_height", + TargetPath: "user_height", Required: true, DataType: "string", DefaultValue: "", }, { SourcePath: "company.name", - MapPath: "company_name", + TargetPath: "company_name", Required: true, DataType: "string", DefaultValue: "", }, { SourcePath: "company.start", - MapPath: "company_start", + TargetPath: "company_start", Required: true, DataType: "string", DefaultValue: "", @@ -105,7 +106,7 @@ func TestNewFilterForArrayOne(t *testing.T) { filterRuleList := []MapRule{ { SourcePath: "[].name", - MapPath: "user_name.[]", + TargetPath: "user_name.[]", Required: true, DataType: "string", DefaultValue: "", @@ -145,7 +146,7 @@ func TestNewFilterForArrayTwo(t *testing.T) { filterRuleList := []MapRule{ { SourcePath: "user_list.[].name", - MapPath: "user.name_list.[]", + TargetPath: "user.name_list.[]", Required: true, DataType: "string", DefaultValue: "", @@ -158,3 +159,13 @@ func TestNewFilterForArrayTwo(t *testing.T) { fmt.Println(f.String()) }) } + +func TestAntMap(t *testing.T) { + testMap := map[any]any{ + "name": "zhangde", + 1: 1, + 1.234: 2.345, + } + byteData, err := json.Marshal(testMap) + fmt.Println(string(byteData), err) +}