// Package filter ... // // Description : filter ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2024-04-07 21:59 package filter import ( "errors" "fmt" "git.zhangdeman.cn/zhangdeman/data_mask" "git.zhangdeman.cn/zhangdeman/data_mask/define" "github.com/tidwall/gjson" "github.com/tidwall/sjson" "strings" ) // Execute 数据转换 // // Author : go_developer@163.com<张德满> // // Date : 12:39 2024/3/26 func Execute(sourceData string, convertRule []*define.FilterRule) *Transform { sourceData = strings.TrimSpace(sourceData) t := &Transform{ sourceData: sourceData, ruleList: convertRule, result: "{}", } return t } // Transform 转换 // // Author : go_developer@163.com<张德满> // // Date : 10:56 2024/3/27 type Transform struct { sourceData string ruleList []*define.FilterRule result string } // Execute 执行 // // Author : go_developer@163.com<张德满> // // Date : 10:57 2024/3/27 func (t *Transform) Execute() error { sourceResult := gjson.Parse(t.sourceData) if !sourceResult.IsObject() { return errors.New("source data is not object") } if err := t.checkRule(); nil != err { return err } for _, itemRule := range t.ruleList { if err := t.rewrite(itemRule); nil != err { return err } } return nil } // GetResult 获取处理结果 // // Author : go_developer@163.com<张德满> // // Date : 11:32 2024/3/27 func (t *Transform) GetResult() string { return t.result } // checkRule 校验规则 // // Author : go_developer@163.com<张德满> // // Date : 11:18 2024/3/27 func (t *Transform) checkRule() error { for _, itemRule := range t.ruleList { itemRule.SourceDataPath = strings.TrimRight(itemRule.SourceDataPath, ".[]") itemRule.TargetDataPath = strings.TrimRight(itemRule.TargetDataPath, ".[]") fromPathArr := strings.Split(itemRule.SourceDataPath, "[]") targetPathArr := strings.Split(itemRule.TargetDataPath, "[]") if len(targetPathArr) > len(fromPathArr) { return errors.New("slice path config invalid : " + itemRule.SourceDataPath + " -> " + itemRule.TargetDataPath) } } return nil } // rewrite 数据重写 // // Author : go_developer@163.com<张德满> // // Date : 11:25 2024/3/27 func (t *Transform) rewrite(rule *define.FilterRule) error { var ( err error ) sourceResult := gjson.Get(t.sourceData, rule.SourceDataPath) if !sourceResult.Exists() { if rule.IsRequired { return errors.New(rule.SourceDataPath + " is not exist, but required") } if strings.Contains(rule.SourceDataPath, "[]") { return t.rewriteForSlice(rule) } // 走的默认值认为无需脱敏 if t.result, err = sjson.Set(t.result, rule.TargetDataPath, rule.DefaultValue); nil != err { return err } return nil } // 数据脱敏 realValue := sourceResult.String() if len(rule.DataMaskStrategy) > 0 { if realValue, err = data_mask.ExecuteWithError(realValue, rule.DataMaskStrategy); nil != err { return err } // 一旦执行数据脱敏, 统一以字符串输出 t.result, err = sjson.Set(t.result, rule.TargetDataPath, realValue) return err } // TODO : 格式转换 t.result, err = sjson.Set(t.result, rule.TargetDataPath, sourceResult.Value()) return err } // rewriteForSlice 数组重写 // // Author : go_developer@163.com<张德满> // // Date : 15:22 2024/3/27 func (t *Transform) rewriteForSlice(rule *define.FilterRule) error { var ( err error ) pathArr := strings.Split(rule.SourceDataPath, ".[].") sliceUnfoldResult := t.unfoldSourceSliceData(t.sourceData, pathArr[0:len(pathArr)-1], nil) targetArr := strings.Split(rule.TargetDataPath, ".[].") for idx, itemRes := range sliceUnfoldResult { if t.result, err = sjson.Set(t.result, fmt.Sprintf("%v.%v.%v", targetArr[0], idx, targetArr[1]), itemRes.Get(pathArr[len(pathArr)-1]).Value()); nil != err { return err } } return nil } // unfoldSourceSliceData 展开元数据的数组, 平铺 // // Author : go_developer@163.com<张德满> // // Date : 17:39 2024/3/27 func (t *Transform) unfoldSourceSliceData(sourceData string, pathList []string, res []gjson.Result) []gjson.Result { if nil == res { res = make([]gjson.Result, 0) } arrRes := gjson.Get(sourceData, pathList[0]).Array() if len(pathList) == 1 { for _, itemRes := range arrRes { res = append(res, itemRes) } return res } for i := 0; i < len(arrRes)-1; i++ { res = t.unfoldSourceSliceData(arrRes[i].String(), pathList[1:], res) } return t.unfoldSourceSliceData(arrRes[len(arrRes)-1].String(), pathList[1:], res) }