// Package filter ... // // Description : filter ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2022-07-04 17:47 package filter import ( "encoding/json" "fmt" "reflect" "strings" "git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack" "git.zhangdeman.cn/zhangdeman/serialize" "github.com/tidwall/gjson" "github.com/tidwall/sjson" "errors" ) // NewFilter 过滤器实例 // // Author : go_developer@163.com<白茶清欢> // // Date : 11:54 2022/7/4 func NewFilter(sourceData string, filterRuleList []MapRule) *filter { return &filter{ sourceData: sourceData, formatResult: "{}", filterRuleList: filterRuleList, } } // filter 数据过滤 // // Author : go_developer@163.com<白茶清欢> // // Date : 11:58 2022/7/4 type filter struct { sourceData string formatResult string filterRuleList []MapRule } // Deal ... // // Author : go_developer@163.com<白茶清欢> // // Date : 11:59 2022/7/4 func (f *filter) Deal() error { var ( err error ) for _, rule := range f.filterRuleList { if len(rule.TargetPath) == 0 { // 未配置目标路径则, 目标路径和源路径保持一致 rule.TargetPath = rule.SourcePath } if f.IsArray(rule) { // 对于list的处理, 展开层级, 并自动追加到f.filterRuleList 后面 if err = f.handleArray(rule); nil != err { return err } continue } if err = f.setResult(rule); nil != err { return err } } return nil } // IsArray 判断是否为数组 // // Author : zhangdeman001@ke.com<张德满> // // Date : 17:48 2023/1/1 func (f *filter) IsArray(rule MapRule) bool { return strings.Contains(rule.SourcePath, gjson_hack.ArrayIdxTpl) } // handleArray 处理数组(最复杂的场景) // // Author : go_developer@163.com<白茶清欢> // // Date : 17:41 2023/1/1 func (f *filter) handleArray(rule MapRule) error { // 对于list的处理, 展开层级, 并自动追加到f.filterRuleList 后面 var ( err error ) expendRes := &gjson_hack.ExpendArrayResult{ PathList: make([]string, 0), PathMap: map[string]string{}, } if err = gjson_hack.ExpandArrayPath(f.sourceData, rule.SourcePath, rule.TargetPath, expendRes); nil != err { return 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 } // 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 } // extraFinalResult 提取全部最底层结果 // // Author : zhangdeman001@ke.com<张德满> // // Date : 14:00 2023/1/2 func (f *filter) getAllFinalData(res *[]string, resultList []gjson.Result, pathArr []string) { if len(pathArr) == 1 { for _, item := range resultList { *res = append(*res, item.Get(pathArr[0]).String()) } return } for _, item := range resultList { f.getAllFinalData(res, item.Array(), pathArr[1:]) } return } // String 获取格式化之后的字符串 // // Author : go_developer@163.com<白茶清欢> // // Date : 21:18 2022/12/31 func (f *filter) String() string { return f.formatResult } // Byte 获取格式化之后的字节数组 // // Author : zhangdeman001@ke.com<张德满> // // Date : 21:18 2022/12/31 func (f *filter) Byte() []byte { return []byte(f.String()) } // Parse 解析返回结果 // // Author : go_developer@163.com<白茶清欢> // // Date : 21:20 2022/12/31 func (f *filter) Parse(receiver interface{}) error { if nil == receiver { return errors.New("receiver is nil") } return json.Unmarshal(f.Byte(), receiver) }