diff --git a/define/filter.go b/define/filter.go new file mode 100644 index 0000000..f994f0a --- /dev/null +++ b/define/filter.go @@ -0,0 +1,25 @@ +// Package define ... +// +// Description : define ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-04-07 21:43 +package define + +import "git.zhangdeman.cn/zhangdeman/data_mask" + +// FilterRule ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 21:43 2024/4/7 +type FilterRule struct { + SourceDataPath string `json:"source_data_path"` // 原始数据路径 + TargetDataPath string `json:"target_data_path"` // 目标数据路径 + IsRequired bool `json:"is_required"` // 要求字段必须存在 + AllowNil bool `json:"allow_nil"` // 允许nil值 + DefaultValue string `json:"default_value"` // 不存在时的默认值 + Type string `json:"type"` // 数据类型 + DataMask data_mask.IDataMask `json:"-"` // 数据脱敏策略 +} diff --git a/filter/filter.go b/filter/filter.go new file mode 100644 index 0000000..4d7bd8b --- /dev/null +++ b/filter/filter.go @@ -0,0 +1,158 @@ +// 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/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 + } + t.result, err = sjson.Set(t.result, rule.TargetDataPath, sourceResult.Value()) + return nil +} + +// rewriteForSlice 数组重写 +// +// Author : go_developer@163.com<张德满> +// +// Date : 15:22 2024/3/27 +func (t *Transform) rewriteForSlice(rule *define.FilterRule) 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 { + t.result, _ = sjson.Set(t.result, fmt.Sprintf("%v.%v.%v", targetArr[0], idx, targetArr[1]), itemRes.Get(pathArr[len(pathArr)-1]).Value()) + } + 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) +} diff --git a/go.mod b/go.mod index 8faba67..4b68c60 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,10 @@ module git.zhangdeman.cn/zhangdeman/data_mask go 1.21 + +require ( + github.com/tidwall/gjson v1.17.1 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ee6346f --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= +github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= diff --git a/strategy/mail.go b/strategy/mail.go index 14162ff..4f0cdfc 100644 --- a/strategy/mail.go +++ b/strategy/mail.go @@ -1,4 +1,4 @@ -// Package data_mask ... +// Package strategy ... // // Description : data_mask ... // diff --git a/strategy/mail_test.go b/strategy/mail_test.go index a16a909..a8b13af 100644 --- a/strategy/mail_test.go +++ b/strategy/mail_test.go @@ -1,4 +1,4 @@ -// Package data_mask ... +// Package strategy ... // // Description : data_mask ... //