gjson+sjson hack升级 #8
@ -43,3 +43,8 @@ type ExpendArrayResult struct {
|
|||||||
PathList []string `json:"path_list"` // 路径列表
|
PathList []string `json:"path_list"` // 路径列表
|
||||||
PathMap map[string]string `json:"path_map"` // 数据源路径 => 目标路径的处理
|
PathMap map[string]string `json:"path_map"` // 数据源路径 => 目标路径的处理
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
SpecialKeyStart = "{{#"
|
||||||
|
SpecialKeyEnd = "#}}"
|
||||||
|
)
|
||||||
|
@ -66,9 +66,9 @@ func doExpandPath(gjsonResult gjson.Result, rootPath string, hasChildren bool, p
|
|||||||
gjsonResult.ForEach(func(key, value gjson.Result) bool {
|
gjsonResult.ForEach(func(key, value gjson.Result) bool {
|
||||||
newRootPath := ""
|
newRootPath := ""
|
||||||
if len(rootPath) == 0 {
|
if len(rootPath) == 0 {
|
||||||
newRootPath = key.String()
|
newRootPath = getPathKey(key.String())
|
||||||
} else {
|
} else {
|
||||||
newRootPath = rootPath + "." + key.String()
|
newRootPath = rootPath + "." + getPathKey(key.String())
|
||||||
}
|
}
|
||||||
if value.IsArray() || value.IsObject() {
|
if value.IsArray() || value.IsObject() {
|
||||||
if !pathOption.OnlyFinalPath {
|
if !pathOption.OnlyFinalPath {
|
||||||
@ -125,9 +125,35 @@ func doExpandPath(gjsonResult gjson.Result, rootPath string, hasChildren bool, p
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getPathKey ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 20:54 2024/12/4
|
||||||
|
func getPathKey(key string) string {
|
||||||
|
if !strings.Contains(key, ".") {
|
||||||
|
// 非特殊key
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
if IsSpecialKey(key) {
|
||||||
|
// 已经是special key
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
return SpecialKeyStart + key + SpecialKeyEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsArrayItemPath 是否为数组子项路径
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 15:49 2024/12/5
|
||||||
|
func IsArrayItemPath(path string) bool {
|
||||||
|
return strings.Contains(path, ArrayIdxTpl)
|
||||||
|
}
|
||||||
|
|
||||||
// ExpandArrayPath 根据真实数据展开数组路径
|
// ExpandArrayPath 根据真实数据展开数组路径
|
||||||
//
|
//
|
||||||
// 路径中若是包含 {{idx}} 占位符, 说明是需要展开的数组, 根据数组的时机数据, 进行数组的逐级展开
|
// 路径中若是包含 {{idx}} 占位符, 说明是需要展开的数组, 根据数组的实际数据, 进行数组的逐级展开
|
||||||
//
|
//
|
||||||
// Author : go_developer@163.com<白茶清欢>
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
//
|
//
|
||||||
@ -145,7 +171,7 @@ func ExpandArrayPath(jsonStr string, pathConfig string, mapConfig string, expend
|
|||||||
if len(mapConfig) == 0 {
|
if len(mapConfig) == 0 {
|
||||||
mapConfig = pathConfig
|
mapConfig = pathConfig
|
||||||
}
|
}
|
||||||
if !strings.Contains(pathConfig, ArrayIdxTpl) {
|
if !IsArrayItemPath(pathConfig) {
|
||||||
// 不是数组模板配置, 无需展开
|
// 不是数组模板配置, 无需展开
|
||||||
expendArrayResult.PathList = append(expendArrayResult.PathList, pathConfig)
|
expendArrayResult.PathList = append(expendArrayResult.PathList, pathConfig)
|
||||||
expendArrayResult.PathMap[pathConfig] = mapConfig
|
expendArrayResult.PathMap[pathConfig] = mapConfig
|
||||||
@ -163,7 +189,7 @@ func ExpandArrayPath(jsonStr string, pathConfig string, mapConfig string, expend
|
|||||||
return errors.New("mapConfig depth not equal pathConfig deep")
|
return errors.New("mapConfig depth not equal pathConfig deep")
|
||||||
}
|
}
|
||||||
|
|
||||||
valueResult := gjson.Parse(jsonStr).Get(pathConfigArr[0])
|
valueResult := Get(gjson.Parse(jsonStr), pathConfigArr[0])
|
||||||
if !valueResult.Exists() {
|
if !valueResult.Exists() {
|
||||||
// 路径不存在, 无需设置具体值
|
// 路径不存在, 无需设置具体值
|
||||||
return nil
|
return nil
|
||||||
@ -240,5 +266,98 @@ func Result(gjsonResult gjson.Result) gjson.Result {
|
|||||||
if IsArray(gjsonResult) {
|
if IsArray(gjsonResult) {
|
||||||
return Array(gjsonResult)
|
return Array(gjsonResult)
|
||||||
}
|
}
|
||||||
|
return Object(gjsonResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get 主要解决 key 中包含 . 的问题
|
||||||
|
//
|
||||||
|
// 如 : {"person.name": "test"} 如何将 person.name 整体作为一个字段而非两个层级
|
||||||
|
//
|
||||||
|
// 解决方案 :
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 20:17 2024/12/4
|
||||||
|
func Get(gjsonResult gjson.Result, path string) gjson.Result {
|
||||||
|
if len(path) == 0 {
|
||||||
|
return gjsonResult
|
||||||
|
}
|
||||||
|
if !gjsonResult.Exists() {
|
||||||
|
return gjsonResult
|
||||||
|
}
|
||||||
|
if !gjsonResult.IsObject() && !gjsonResult.IsArray() {
|
||||||
|
return gjsonResult.Get(path)
|
||||||
|
}
|
||||||
|
if !IsSpecialPath(path) {
|
||||||
|
// 不是特殊路径
|
||||||
|
return gjsonResult.Get(path)
|
||||||
|
}
|
||||||
|
pathArr := strings.Split(path, ".")
|
||||||
|
normalPathList := make([]string, 0)
|
||||||
|
specialKeyList := make([]string, 0)
|
||||||
|
specialKeyHasStart := false
|
||||||
|
for idx, item := range pathArr {
|
||||||
|
if strings.HasPrefix(item, SpecialKeyStart) {
|
||||||
|
specialKeyHasStart = true
|
||||||
|
specialKeyList = append(specialKeyList, item)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(item, SpecialKeyEnd) {
|
||||||
|
specialKeyHasStart = false
|
||||||
|
specialKeyList = append(specialKeyList, item)
|
||||||
|
sourceResult := gjsonResult
|
||||||
|
if len(normalPathList) > 0 {
|
||||||
|
sourceResult = gjsonResult.Get(strings.Join(normalPathList, "."))
|
||||||
|
}
|
||||||
|
realKeyName := GetRealKeyName(strings.Join(specialKeyList, "."))
|
||||||
|
return Get(sourceResult.Map()[realKeyName], strings.Join(pathArr[idx+1:], "."))
|
||||||
|
}
|
||||||
|
if specialKeyHasStart {
|
||||||
|
specialKeyList = append(specialKeyList, item)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
normalPathList = append(normalPathList, item)
|
||||||
|
}
|
||||||
return gjsonResult
|
return gjsonResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetMany 兼容 gjson GetMany 方法
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 16:32 2024/12/5
|
||||||
|
func GetMany(jsonStr string, pathList ...string) []gjson.Result {
|
||||||
|
res := make([]gjson.Result, 0)
|
||||||
|
gjsonResult := gjson.Parse(jsonStr)
|
||||||
|
for _, itemPath := range pathList {
|
||||||
|
res = append(res, Get(gjsonResult, itemPath))
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSpecialPath 判断传入的是否为特殊路径
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 20:27 2024/12/4
|
||||||
|
func IsSpecialPath(path string) bool {
|
||||||
|
return strings.Contains(path, SpecialKeyStart) && strings.Contains(path, SpecialKeyEnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSpecialKey 判断是否特殊key
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 20:29 2024/12/4
|
||||||
|
func IsSpecialKey(key string) bool {
|
||||||
|
return strings.HasPrefix(key, SpecialKeyStart) && strings.HasSuffix(key, SpecialKeyEnd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRealKeyName ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 20:31 2024/12/4
|
||||||
|
func GetRealKeyName(key string) string {
|
||||||
|
return strings.TrimSuffix(strings.TrimPrefix(key, SpecialKeyStart), SpecialKeyEnd)
|
||||||
|
}
|
||||||
|
@ -12,8 +12,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tidwall/sjson"
|
|
||||||
|
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -98,13 +96,14 @@ func TestPathOnlyFinallyPathWithUnfoldArray(t *testing.T) {
|
|||||||
"company_info": map[string]any{
|
"company_info": map[string]any{
|
||||||
"address": "Beijing",
|
"address": "Beijing",
|
||||||
"email": "xxx@xxx.com",
|
"email": "xxx@xxx.com",
|
||||||
|
"a.b": "cd",
|
||||||
},
|
},
|
||||||
"sex": "man",
|
"sex": "man",
|
||||||
"user_list": [][]map[string]any{
|
"user_list": [][]map[string]any{
|
||||||
[]map[string]any{
|
[]map[string]any{
|
||||||
{"name": "zhang", "age": 10},
|
{"name": "zhang", "age": 10, "e.f": "g"},
|
||||||
{"name": "li", "age": 20},
|
{"name": "li", "age": 20, "e.f": "g"},
|
||||||
{"name": "wang", "age": 30},
|
{"name": "wang", "age": 30, "e.f": "g"},
|
||||||
},
|
},
|
||||||
[]map[string]any{
|
[]map[string]any{
|
||||||
{"name": "zhang", "age": 10},
|
{"name": "zhang", "age": 10},
|
||||||
@ -136,13 +135,14 @@ func TestPathOnlyFinallyPathWithUnfoldArray(t *testing.T) {
|
|||||||
func TestExpandArrayPath(t *testing.T) {
|
func TestExpandArrayPath(t *testing.T) {
|
||||||
mapData := map[string]any{
|
mapData := map[string]any{
|
||||||
"person_list": []map[string]any{
|
"person_list": []map[string]any{
|
||||||
{"name": "zhang", "age": 10},
|
{"name": "zhang", "age": 10, "a.b": "people_name"},
|
||||||
{"name": "li", "age": 20},
|
{"name": "li", "age": 20, "a.b": "people_name"},
|
||||||
{"name": "wang", "age": 30},
|
{"name": "wang", "age": 30, "a.b": "people_name"},
|
||||||
},
|
},
|
||||||
"company_info": map[string]any{
|
"company_info": map[string]any{
|
||||||
"address": "Beijing",
|
"address": "Beijing",
|
||||||
"email": "xxx@xxx.com",
|
"email": "xxx@xxx.com",
|
||||||
|
"level.a.b": "deep level",
|
||||||
},
|
},
|
||||||
"sex": "man",
|
"sex": "man",
|
||||||
"user_list": [][]map[string]any{
|
"user_list": [][]map[string]any{
|
||||||
@ -170,12 +170,32 @@ func TestExpandArrayPath(t *testing.T) {
|
|||||||
PathList: nil,
|
PathList: nil,
|
||||||
PathMap: nil,
|
PathMap: nil,
|
||||||
}
|
}
|
||||||
|
ExpandArrayPath(jsonStr, "company_info.{{#level.a.b#}}", "company_info.a-b", pathExpendRes)
|
||||||
|
ExpandArrayPath(jsonStr, "person_list.{{idx}}.{{#a.b#}}", "person_list.{{idx}}.a-b", pathExpendRes)
|
||||||
ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.age", "a.{{idx}}.{{idx}}.b", pathExpendRes)
|
ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.age", "a.{{idx}}.{{idx}}.b", pathExpendRes)
|
||||||
ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.name", "e.{{idx}}.{{idx}}.c", pathExpendRes)
|
ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.name", "e.{{idx}}.{{idx}}.c", pathExpendRes)
|
||||||
ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.sex", "f.{{idx}}.{{idx}}.c", pathExpendRes)
|
ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.sex", "f.{{idx}}.{{idx}}.c", pathExpendRes)
|
||||||
res := ""
|
// res := ""
|
||||||
for _, item := range pathExpendRes.PathList {
|
for _, item := range pathExpendRes.PathList {
|
||||||
res, _ = sjson.Set(res, pathExpendRes.PathMap[item], gjson.Get(jsonStr, item).Value())
|
// fmt.Println(item, pathExpendRes.PathMap[item])
|
||||||
|
fmt.Println(item, pathExpendRes.PathMap[item], Get(gjson.Parse(jsonStr), item).String())
|
||||||
|
// res, _ = sjson.Set(res, pathExpendRes.PathMap[item], Get(gjson.Parse(jsonStr), item).Value())
|
||||||
}
|
}
|
||||||
fmt.Println(res)
|
}
|
||||||
|
|
||||||
|
func TestGet(t *testing.T) {
|
||||||
|
mapData := map[string]any{
|
||||||
|
"person.name": "test",
|
||||||
|
"test": map[string]any{
|
||||||
|
"a.b": "c",
|
||||||
|
"d.e": map[string]any{
|
||||||
|
"e.f": "g",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
byteData, _ := json.Marshal(mapData)
|
||||||
|
gjsonResult := gjson.ParseBytes(byteData)
|
||||||
|
fmt.Println(Get(gjsonResult, "{{#person.name#}}").String())
|
||||||
|
fmt.Println(Get(gjsonResult, "test.{{#a.b#}}").String())
|
||||||
|
fmt.Println(Get(gjsonResult, "test.{{#d.e#}}.{{#e.f#}}").String())
|
||||||
}
|
}
|
||||||
|
68
sjson_hack/set.go
Normal file
68
sjson_hack/set.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Package sjson_hack ...
|
||||||
|
//
|
||||||
|
// Description : sjson_hack ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2024-12-03 11:36
|
||||||
|
package sjson_hack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||||
|
"github.com/tidwall/sjson"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
reg = regexp.MustCompile(`({\{\#.*?\#\}\})`)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set 设置路径的值
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 11:36 2024/12/3
|
||||||
|
func Set(jsonRes string, path string, value any) (string, error) {
|
||||||
|
fmt.Println(jsonRes, value)
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
res string = jsonRes
|
||||||
|
)
|
||||||
|
|
||||||
|
// 包含特殊字符串, 匹配出特殊字符串
|
||||||
|
specialKeyList := getSpecialKeyList(path)
|
||||||
|
specialKeyTale := map[string]string{}
|
||||||
|
for _, item := range specialKeyList {
|
||||||
|
// 替换掉占位字符串
|
||||||
|
specialKeyTale[item] = wrapper.StringFromRandom(64, "").Md5().Value
|
||||||
|
path = strings.ReplaceAll(path, item, specialKeyTale[item])
|
||||||
|
}
|
||||||
|
|
||||||
|
if res, err = sjson.Set(res, path, value); nil != err {
|
||||||
|
return "", errors.New(path + " -> set json fail:" + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将特殊字符串替换回来
|
||||||
|
for sourceKey, convertKey := range specialKeyTale {
|
||||||
|
res = strings.ReplaceAll(res, convertKey, gjson_hack.GetRealKeyName(sourceKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getSpecialKeyList 获取特殊key列表
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 17:35 2024/12/5
|
||||||
|
func getSpecialKeyList(path string) []string {
|
||||||
|
matchList := reg.FindAllString(path, -1)
|
||||||
|
if len(matchList) == 0 {
|
||||||
|
return make([]string, 0)
|
||||||
|
}
|
||||||
|
return matchList
|
||||||
|
}
|
18
sjson_hack/set_test.go
Normal file
18
sjson_hack/set_test.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Package sjson_hack ...
|
||||||
|
//
|
||||||
|
// Description : sjson_hack ...
|
||||||
|
//
|
||||||
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
|
//
|
||||||
|
// Date : 2024-12-05 17:32
|
||||||
|
package sjson_hack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSet(t *testing.T) {
|
||||||
|
res, err := Set("{}", "{{#a.b#}}.c.{{#c.d#}}.e", "test")
|
||||||
|
fmt.Println(res, err)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user