// Package json_tool ... // // Description : json_tool ... // // Author : go_developer@163.com<张德满> // // Date : 2022/01/22 9:19 PM package json_tool import ( "fmt" "io" "log" "os" "strings" "github.com/pkg/errors" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) const ( virtualRoot = "__virtual__root" ) // FilterOption 过滤选项 // // Author : go_developer@163.com<白茶清欢> // // Date : 17:59 2023/9/1 type FilterOption struct { DebugModel bool // 调试模式 LogInstance io.Writer // 日志实例 } // FilterDataRule 参数过滤规则 // // Author : go_developer@163.com<白茶清欢> // // Date : 2022/1/22 9:44 PM type FilterDataRule struct { SourceKey string // 原始数据路径 MapKey string // 提取后映射到的数据路径 DefaultValue interface{} // 原始数据路径不存在时的默认值 WithDefault bool // 是否使用默认值 } // NewDataFilter 获取数据过滤方法实例 // // Author : go_developer@163.com<白茶清欢> // // Date : 2022/1/22 9:50 PM func NewDataFilter(source string, filterRule []*FilterDataRule, filterOption *FilterOption) *DataFilter { if nil == filterOption { filterOption = &FilterOption{} } if filterOption.DebugModel && nil == filterOption.LogInstance { filterOption.LogInstance = os.Stdout log.SetOutput(filterOption.LogInstance) } return &DataFilter{ source: source, filterRule: filterRule, rewriteResult: "{}", filterOption: filterOption, } } // DataFilter 数据过滤 // // Author : go_developer@163.com<白茶清欢> // // Date : 2022/1/22 9:20 PM type DataFilter struct { source string filterRule []*FilterDataRule rewriteResult string // json数据重写结果 filterOption *FilterOption // 过滤选项 } // Filter 数据过滤 // // Author : go_developer@163.com<白茶清欢> // // Date : 2022/1/22 9:36 PM func (df *DataFilter) Filter() (string, error) { df.logPrint(logLevelDebug, "source_data => ", df.source) var ( err error ) for _, itemRule := range df.filterRule { sourceIsArr := df.isArrPath(itemRule.SourceKey) mapIsArr := df.isArrPath(itemRule.MapKey) if !sourceIsArr && !mapIsArr { // 输入输出均不是数组, 最简单的场景 if err = df.setKV(itemRule); nil != err { return "", err } } sourcePathArr := df.getArrPathList(itemRule.SourceKey) mapPathArr := df.getArrPathList(itemRule.MapKey) if len(mapPathArr) > len(sourcePathArr) { df.logPrint(logLevelFatal, "映射的层级深度大于数据源深度", "source_path => "+itemRule.SourceKey, "map_path => "+itemRule.MapKey) return "", fmt.Errorf("映射的层级深度大于数据源深度, source_path => %v map_path => %v", itemRule.SourceKey, itemRule.MapKey) } if !mapIsArr { } } return df.rewriteResult, nil } // isArrPath 是否为数组路径 // // Author : go_developer@163.com<白茶清欢> // // Date : 16:00 2023/9/1 func (df *DataFilter) isArrPath(path string) bool { return strings.Contains(path, "[]") } // a.[].b.[].c.[].d // e.[].f.[].g func (df *DataFilter) getDataAsSlice(sourceData string, pathList []string) []interface{} { //fmt.Println(sourceData, pathList) result := make([]interface{}, 0) if len(pathList) == 0 { return result } if len(pathList) == 1 { return []interface{}{gjson.Get(sourceData, pathList[0]).Value()} } for idx, itemPath := range pathList { if len(pathList)-1 == idx { val := gjson.Get(sourceData, itemPath).Value() if nil == val { return result } result = append(result, val) return result } currentPathVal := gjson.Get(sourceData, itemPath).Array() for _, sonItem := range currentPathVal { result = append(result, df.getDataAsSlice(sonItem.String(), pathList[idx:])...) } } return result } // setValue 设置值 // // Author : go_developer@163.com<白茶清欢> // // Date : 22:04 2023/9/1 func (df *DataFilter) setValue(path string, value interface{}) error { var ( err error ) df.rewriteResult, err = sjson.Set(df.rewriteResult, path, value) return err } // setKV 设置相关值 // // Author : go_developer@163.com<白茶清欢> // // Date : 16:03 2023/9/1 func (df *DataFilter) setKV(rule *FilterDataRule) error { var ( err error ) sourceValue := gjson.Get(df.source, rule.SourceKey) if sourceValue.Exists() { // 原始数据存在对应路径 df.rewriteResult, err = sjson.Set(df.rewriteResult, rule.MapKey, sourceValue.Value()) return err } if !rule.WithDefault { // 路径不存在, 且禁用默认值 return errors.New(rule.SourceKey + " : source path not found, and default value is forbidden") } // 使用默认值填充 df.rewriteResult, err = sjson.Set(df.rewriteResult, rule.MapKey, rule.DefaultValue) return err } // getArrPathList 获取路径列表 // // Author : go_developer@163.com<白茶清欢> // // Date : 21:32 2023/9/1 func (df *DataFilter) getArrPathList(inputPath string) []string { pathArr := strings.Split(inputPath, "[]") arr := make([]string, 0) for _, item := range pathArr { arr = append(arr, strings.Trim(item, ".")) } return arr } // logPrint 打印日志 // // Author : go_developer@163.com<白茶清欢> // // Date : 18:00 2023/9/1 func (df *DataFilter) logPrint(level string, msg string, logAttr ...interface{}) { if !df.filterOption.DebugModel { // 未开启调试模式 return } logData := append([]interface{}{level, msg}, logAttr...) log.Println(logData...) } // 日志等级定义 const ( logLevelPanic = "PANIC" logLevelFatal = "FATAL" logLevelWarn = "WARN" logLevelInfo = "INFO" logLevelDebug = "DEBUG" )