Files
json_filter/gjson_hack/path.go

186 lines
5.4 KiB
Go

// Package gjson_hack ...
//
// Description : gjson_hack ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-11-27 11:58
package gjson_hack
import (
"errors"
"fmt"
"strings"
"github.com/tidwall/gjson"
)
// newDefaultPathOption 默认路径展开选项
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:06 2024/11/27
func newDefaultPathOption() *PathOption {
return &PathOption{
UnfoldArray: true,
MaxDeep: 0,
OnlyFinalPath: false,
}
}
// newPathResult ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:17 2024/11/27
func newPathResult() *PathResult {
return &PathResult{
List: make([]string, 0),
ValueTable: make(map[string]gjson.Result),
}
}
// Path 查看全部路径
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:03 2024/11/27
func Path(jsonStr string, pathOption *PathOption) (*PathResult, error) {
gjsonResult := gjson.Parse(jsonStr)
pathResult := newPathResult()
if nil == pathOption {
pathOption = newDefaultPathOption()
}
doExpandPath(gjsonResult, "", true, pathOption, pathResult)
return pathResult, nil
}
// doExpandPath 展开路径
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:57 2024/11/27
func doExpandPath(gjsonResult gjson.Result, rootPath string, hasChildren bool, pathOption *PathOption, pathResult *PathResult) {
if gjsonResult.IsObject() {
// 处理object
gjsonResult.ForEach(func(key, value gjson.Result) bool {
newRootPath := ""
if len(rootPath) == 0 {
newRootPath = key.String()
} else {
newRootPath = rootPath + "." + key.String()
}
if value.IsArray() || value.IsObject() {
if !pathOption.OnlyFinalPath {
// 中间key路径也存储下来
pathResult.List = append(pathResult.List, newRootPath)
pathResult.ValueTable[newRootPath] = value
}
doExpandPath(value, newRootPath, true, pathOption, pathResult)
} else {
pathResult.List = append(pathResult.List, newRootPath)
pathResult.ValueTable[newRootPath] = value
}
return true
})
}
if gjsonResult.IsArray() {
arrayList := gjsonResult.Array()
if len(arrayList) == 0 {
pathResult.List = append(pathResult.List, rootPath)
pathResult.ValueTable[rootPath] = gjsonResult
return
}
if arrayList[0].IsObject() || arrayList[0].IsArray() {
// 每一项是对象或者数组
if pathOption.UnfoldArray {
// 展开数组
for _, itemRes := range arrayList {
// doExpandPath(itemRes, rootPath+"."+fmt.Sprintf("%v", idx), true, pathOption, pathResult)
doExpandPath(itemRes, rootPath+"."+ArrayIdxTpl, true, pathOption, pathResult)
}
} else {
// 不展开数组
doExpandPath(arrayList[0], rootPath+".#", true, pathOption, pathResult)
}
} else {
// 每一项是基础类型
pathResult.List = append(pathResult.List, rootPath)
pathResult.ValueTable[rootPath] = gjsonResult
return
}
}
if strings.HasSuffix(rootPath, ".#") || strings.HasSuffix(rootPath, ArrayIdxTpl) {
// 处理不展开类型数组
return
}
if pathOption.OnlyFinalPath && hasChildren {
// 仅记录最终完整路径, 中间路径不记录
return
}
if _, exist := pathResult.ValueTable[rootPath]; !exist {
pathResult.List = append(pathResult.List, rootPath)
pathResult.ValueTable[rootPath] = gjsonResult
}
return
}
// ExpandArrayPath 根据真实数据展开数组路径
//
// 路径中若是包含 {{idx}} 占位符, 说明是需要展开的数组, 根据数组的时机数据, 进行数组的逐级展开
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:13 2024/11/29
func ExpandArrayPath(jsonStr string, pathConfig string, mapConfig string, expendArrayResult *ExpendArrayResult) error {
if nil == expendArrayResult {
return errors.New("expendArrayResult can not be nil")
}
if nil == expendArrayResult.PathList {
expendArrayResult.PathList = make([]string, 0)
}
if nil == expendArrayResult.PathMap {
expendArrayResult.PathMap = make(map[string]string)
}
if len(mapConfig) == 0 {
mapConfig = pathConfig
}
if !strings.Contains(pathConfig, ArrayIdxTpl) {
// 不是数组模板配置, 无需展开
expendArrayResult.PathList = append(expendArrayResult.PathList, pathConfig)
expendArrayResult.PathMap[pathConfig] = mapConfig
return nil
}
mapConfigArr := strings.Split(mapConfig, ArrayIdxTpl)
mapConfigArr[0] = strings.TrimSuffix(mapConfigArr[0], ".")
mapSuffixPathTpl := strings.TrimPrefix(strings.Join(mapConfigArr[1:], ArrayIdxTpl), ".")
pathConfigArr := strings.Split(pathConfig, ArrayIdxTpl)
pathConfigArr[0] = strings.TrimSuffix(pathConfigArr[0], ".")
suffixPathTpl := strings.TrimPrefix(strings.Join(pathConfigArr[1:], ArrayIdxTpl), ".")
if len(mapConfigArr) != len(pathConfigArr) {
return errors.New("mapConfig depth not equal pathConfig deep")
}
valueResult := gjson.Parse(jsonStr).Get(pathConfigArr[0])
if !valueResult.Exists() {
// 路径不存在, 无需设置具体值
return nil
}
if !valueResult.IsArray() {
// 不是数组,不要继续再向后展开了
expendArrayResult.PathList = append(expendArrayResult.PathList, pathConfigArr[0])
expendArrayResult.PathMap[pathConfigArr[0]] = mapConfigArr[0]
return nil
}
// 继续展开子项
for idx, _ := range valueResult.Array() {
idxStr := fmt.Sprintf("%v", idx)
if err := ExpandArrayPath(jsonStr, pathConfigArr[0]+"."+idxStr+"."+suffixPathTpl, mapConfigArr[0]+"."+idxStr+"."+mapSuffixPathTpl, expendArrayResult); nil != err {
return err
}
}
return nil
}