From 355144b623ce6f7c52a32642e2012f7233c67f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Wed, 4 Dec 2024 20:15:42 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BC=98=E5=8C=96Result?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gjson_hack/path.go | 2 +- sjson_hack/set.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 sjson_hack/set.go diff --git a/gjson_hack/path.go b/gjson_hack/path.go index 2e7995a..1814ab8 100644 --- a/gjson_hack/path.go +++ b/gjson_hack/path.go @@ -240,5 +240,5 @@ func Result(gjsonResult gjson.Result) gjson.Result { if IsArray(gjsonResult) { return Array(gjsonResult) } - return gjsonResult + return Object(gjsonResult) } diff --git a/sjson_hack/set.go b/sjson_hack/set.go new file mode 100644 index 0000000..f1075a2 --- /dev/null +++ b/sjson_hack/set.go @@ -0,0 +1,39 @@ +// Package sjson_hack ... +// +// Description : sjson_hack ... +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 2024-12-03 11:36 +package sjson_hack + +import "strings" + +// Set 设置路径的值 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:36 2024/12/3 +func Set(jsonRes string, path string, value any) (string, error) { + if !isPathHasSpecialChar(path) { + // 不包含特殊字符 + } + return "", nil +} + +// isPathHasSpecialChar 判断路径中是否包含特殊字符 +// +// Author : go_developer@163.com<白茶清欢> +// +// Date : 11:38 2024/12/3 +func isPathHasSpecialChar(path string) bool { + specialCharList := []string{ + ".", + } + for _, itemChar := range specialCharList { + if strings.Contains(path, itemChar) { + return true + } + } + return false +} -- 2.36.6 From 48639ba59a05cc1fbf6ed4fcff9e89935a7eecb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Wed, 4 Dec 2024 20:50:13 +0800 Subject: [PATCH 2/6] =?UTF-8?q?gjson=E8=AF=BB=E5=8F=96=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=94=AF=E6=8C=81key=E5=90=8D=E7=A7=B0=E4=B8=AD=E5=8C=85?= =?UTF-8?q?=E5=90=AB.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gjson_hack/define.go | 5 +++ gjson_hack/path.go | 79 +++++++++++++++++++++++++++++++++++++++++ gjson_hack/path_test.go | 17 +++++++++ 3 files changed, 101 insertions(+) diff --git a/gjson_hack/define.go b/gjson_hack/define.go index 577d477..bf9fb3c 100644 --- a/gjson_hack/define.go +++ b/gjson_hack/define.go @@ -43,3 +43,8 @@ type ExpendArrayResult struct { PathList []string `json:"path_list"` // 路径列表 PathMap map[string]string `json:"path_map"` // 数据源路径 => 目标路径的处理 } + +const ( + SpecialKeyStart = "{{#" + SpecialKeyEnd = "#}}" +) diff --git a/gjson_hack/path.go b/gjson_hack/path.go index 1814ab8..10ef86c 100644 --- a/gjson_hack/path.go +++ b/gjson_hack/path.go @@ -242,3 +242,82 @@ func Result(gjsonResult gjson.Result) gjson.Result { } 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 + } + if !IsSpecialPath(path) { + // 不是特殊路径 + return gjsonResult + } + 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 +} + +// 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) +} diff --git a/gjson_hack/path_test.go b/gjson_hack/path_test.go index 1848b11..0d22ce4 100644 --- a/gjson_hack/path_test.go +++ b/gjson_hack/path_test.go @@ -179,3 +179,20 @@ func TestExpandArrayPath(t *testing.T) { } 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()) +} -- 2.36.6 From df6e554d037d1da06d45e3b416072c1e86a35ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Thu, 5 Dec 2024 16:09:18 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E4=BF=AE=E5=A4=8DGet=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9A=84BUG=20+=20=E5=8D=87=E7=BA=A7=E5=9F=BA=E4=BA=8E?= =?UTF-8?q?=E5=AE=9E=E9=99=85=E6=95=B0=E6=8D=AE=E5=B1=95=E5=BC=80=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BB=84=E7=9C=9F=E5=AE=9E=E8=B7=AF=E5=BE=84=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E6=B3=95ExpandArrayPath?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gjson_hack/path.go | 40 +++++++++++++++++++++++++++++++++------- gjson_hack/path_test.go | 22 ++++++++++++---------- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/gjson_hack/path.go b/gjson_hack/path.go index 10ef86c..496585f 100644 --- a/gjson_hack/path.go +++ b/gjson_hack/path.go @@ -66,9 +66,9 @@ func doExpandPath(gjsonResult gjson.Result, rootPath string, hasChildren bool, p gjsonResult.ForEach(func(key, value gjson.Result) bool { newRootPath := "" if len(rootPath) == 0 { - newRootPath = key.String() + newRootPath = getPathKey(key.String()) } else { - newRootPath = rootPath + "." + key.String() + newRootPath = rootPath + "." + getPathKey(key.String()) } if value.IsArray() || value.IsObject() { if !pathOption.OnlyFinalPath { @@ -125,9 +125,35 @@ func doExpandPath(gjsonResult gjson.Result, rootPath string, hasChildren bool, p 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 根据真实数据展开数组路径 // -// 路径中若是包含 {{idx}} 占位符, 说明是需要展开的数组, 根据数组的时机数据, 进行数组的逐级展开 +// 路径中若是包含 {{idx}} 占位符, 说明是需要展开的数组, 根据数组的实际数据, 进行数组的逐级展开 // // Author : go_developer@163.com<白茶清欢> // @@ -145,7 +171,7 @@ func ExpandArrayPath(jsonStr string, pathConfig string, mapConfig string, expend if len(mapConfig) == 0 { mapConfig = pathConfig } - if !strings.Contains(pathConfig, ArrayIdxTpl) { + if !IsArrayItemPath(pathConfig) { // 不是数组模板配置, 无需展开 expendArrayResult.PathList = append(expendArrayResult.PathList, pathConfig) 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") } - valueResult := gjson.Parse(jsonStr).Get(pathConfigArr[0]) + valueResult := Get(gjson.Parse(jsonStr), pathConfigArr[0]) if !valueResult.Exists() { // 路径不存在, 无需设置具体值 return nil @@ -260,11 +286,11 @@ func Get(gjsonResult gjson.Result, path string) gjson.Result { return gjsonResult } if !gjsonResult.IsObject() && !gjsonResult.IsArray() { - return gjsonResult + return gjsonResult.Get(path) } if !IsSpecialPath(path) { // 不是特殊路径 - return gjsonResult + return gjsonResult.Get(path) } pathArr := strings.Split(path, ".") normalPathList := make([]string, 0) diff --git a/gjson_hack/path_test.go b/gjson_hack/path_test.go index 0d22ce4..41b4914 100644 --- a/gjson_hack/path_test.go +++ b/gjson_hack/path_test.go @@ -12,8 +12,6 @@ import ( "fmt" "testing" - "github.com/tidwall/sjson" - "github.com/tidwall/gjson" ) @@ -136,13 +134,14 @@ func TestPathOnlyFinallyPathWithUnfoldArray(t *testing.T) { func TestExpandArrayPath(t *testing.T) { mapData := map[string]any{ "person_list": []map[string]any{ - {"name": "zhang", "age": 10}, - {"name": "li", "age": 20}, - {"name": "wang", "age": 30}, + {"name": "zhang", "age": 10, "a.b": "people_name"}, + {"name": "li", "age": 20, "a.b": "people_name"}, + {"name": "wang", "age": 30, "a.b": "people_name"}, }, "company_info": map[string]any{ - "address": "Beijing", - "email": "xxx@xxx.com", + "address": "Beijing", + "email": "xxx@xxx.com", + "level.a.b": "deep level", }, "sex": "man", "user_list": [][]map[string]any{ @@ -170,14 +169,17 @@ func TestExpandArrayPath(t *testing.T) { PathList: 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}}.name", "e.{{idx}}.{{idx}}.c", pathExpendRes) ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.sex", "f.{{idx}}.{{idx}}.c", pathExpendRes) - res := "" + // res := "" 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) { -- 2.36.6 From f88826411fee3de0b42819e2488a14c2de388228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Thu, 5 Dec 2024 16:14:10 +0800 Subject: [PATCH 4/6] add test --- gjson_hack/path_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gjson_hack/path_test.go b/gjson_hack/path_test.go index 41b4914..5654f1e 100644 --- a/gjson_hack/path_test.go +++ b/gjson_hack/path_test.go @@ -96,13 +96,14 @@ func TestPathOnlyFinallyPathWithUnfoldArray(t *testing.T) { "company_info": map[string]any{ "address": "Beijing", "email": "xxx@xxx.com", + "a.b": "cd", }, "sex": "man", "user_list": [][]map[string]any{ []map[string]any{ - {"name": "zhang", "age": 10}, - {"name": "li", "age": 20}, - {"name": "wang", "age": 30}, + {"name": "zhang", "age": 10, "e.f": "g"}, + {"name": "li", "age": 20, "e.f": "g"}, + {"name": "wang", "age": 30, "e.f": "g"}, }, []map[string]any{ {"name": "zhang", "age": 10}, -- 2.36.6 From f61f9b28b113ade5b2f2abd30dcc148ef4a9b13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Thu, 5 Dec 2024 16:34:29 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E7=9A=84GetMany=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gjson_hack/path.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/gjson_hack/path.go b/gjson_hack/path.go index 496585f..85e3f7b 100644 --- a/gjson_hack/path.go +++ b/gjson_hack/path.go @@ -321,6 +321,20 @@ func Get(gjsonResult gjson.Result, path string) gjson.Result { 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<白茶清欢> -- 2.36.6 From 96ff37647002dee6fa6792c63d986affb4772a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E8=8C=B6=E6=B8=85=E6=AC=A2?= Date: Thu, 5 Dec 2024 18:49:04 +0800 Subject: [PATCH 6/6] =?UTF-8?q?sjson=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AEke?= =?UTF-8?q?y=E4=B8=AD=E5=8C=85=E5=90=AB=20.=20=E5=AD=97=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sjson_hack/set.go | 59 +++++++++++++++++++++++++++++++----------- sjson_hack/set_test.go | 18 +++++++++++++ 2 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 sjson_hack/set_test.go diff --git a/sjson_hack/set.go b/sjson_hack/set.go index f1075a2..809fb11 100644 --- a/sjson_hack/set.go +++ b/sjson_hack/set.go @@ -7,7 +7,19 @@ // Date : 2024-12-03 11:36 package sjson_hack -import "strings" +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 设置路径的值 // @@ -15,25 +27,42 @@ import "strings" // // Date : 11:36 2024/12/3 func Set(jsonRes string, path string, value any) (string, error) { - if !isPathHasSpecialChar(path) { - // 不包含特殊字符 + 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]) } - return "", nil + + 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 } -// isPathHasSpecialChar 判断路径中是否包含特殊字符 +// getSpecialKeyList 获取特殊key列表 // // Author : go_developer@163.com<白茶清欢> // -// Date : 11:38 2024/12/3 -func isPathHasSpecialChar(path string) bool { - specialCharList := []string{ - ".", +// Date : 17:35 2024/12/5 +func getSpecialKeyList(path string) []string { + matchList := reg.FindAllString(path, -1) + if len(matchList) == 0 { + return make([]string, 0) } - for _, itemChar := range specialCharList { - if strings.Contains(path, itemChar) { - return true - } - } - return false + return matchList } diff --git a/sjson_hack/set_test.go b/sjson_hack/set_test.go new file mode 100644 index 0000000..b492da9 --- /dev/null +++ b/sjson_hack/set_test.go @@ -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) +} -- 2.36.6