Compare commits
56 Commits
78b3ae43e5
...
feature/js
Author | SHA1 | Date | |
---|---|---|---|
b8c8c9d433 | |||
96ff376470 | |||
f61f9b28b1 | |||
f88826411f | |||
df6e554d03 | |||
48639ba59a | |||
355144b623 | |||
ee2326af91 | |||
5b509aaee7 | |||
5fc2e0a613 | |||
7214767a90 | |||
4a318f3638 | |||
d25e579ecf | |||
5ae1841023 | |||
d466b7526d | |||
c10486b403 | |||
8cca556d6f | |||
68d3d76062 | |||
ce1e7fe9da | |||
c1775552cc | |||
0ca808c4fb | |||
cb23772664 | |||
be69c71d4a | |||
7743ee14ce | |||
69066c35c2 | |||
33815072ea | |||
435edb0ea3 | |||
d115e1c5ba | |||
fd1f3367ed | |||
fcf1a7fbd4 | |||
44de8814d8 | |||
31af48e926 | |||
eba6a67875 | |||
3107ca239f | |||
0e4fabcaee | |||
d5db651282 | |||
b6a27fffd5 | |||
cd52bbb02b | |||
45b7aea925 | |||
60c8893537 | |||
00a7b0a47a | |||
3b77b6fbd8 | |||
024f35ac67 | |||
2230411f76 | |||
f3baa17bd5 | |||
2634c53b79 | |||
34913edf28 | |||
e79ac95858 | |||
bae9380210 | |||
8fd5b54a0c | |||
e6c97685e7 | |||
f802550a49 | |||
48f3d80275 | |||
435b339604 | |||
1cdf5449fd | |||
81f9c552dd |
14
define.go
14
define.go
@ -7,15 +7,19 @@
|
||||
// Date : 2022-07-04 18:02
|
||||
package filter
|
||||
|
||||
import (
|
||||
"git.zhangdeman.cn/zhangdeman/consts"
|
||||
)
|
||||
|
||||
// MapRule 映射规则
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:21 2022/7/4
|
||||
type MapRule struct {
|
||||
SourcePath string `json:"source_path"` // 原路径
|
||||
MapPath string `json:"map_path"` // 映射路径
|
||||
Required bool `json:"required"` // 必须存在
|
||||
DataType string `json:"data_type"` // 数据类型
|
||||
DefaultValue string `json:"default_value"` // 默认值, 以字符串传入, 会转换成 DataType
|
||||
SourcePath string `json:"source_path"` // 原路径
|
||||
TargetPath string `json:"target_path"` // 目标路径路径
|
||||
Required bool `json:"required"` // 必须存在
|
||||
DataType consts.DataType `json:"data_type"` // 数据类型
|
||||
DefaultValue string `json:"default_value"` // 默认值, 以字符串传入, 会转换成 DataType
|
||||
}
|
||||
|
161
filter.go
161
filter.go
@ -10,9 +10,11 @@ package filter
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack"
|
||||
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
|
||||
@ -50,23 +52,22 @@ type filter struct {
|
||||
// Date : 11:59 2022/7/4
|
||||
func (f *filter) Deal() error {
|
||||
var (
|
||||
err error
|
||||
formatVal interface{}
|
||||
err error
|
||||
)
|
||||
|
||||
for _, rule := range f.filterRuleList {
|
||||
if len(rule.TargetPath) == 0 {
|
||||
// 未配置目标路径则, 目标路径和源路径保持一致
|
||||
rule.TargetPath = rule.SourcePath
|
||||
}
|
||||
if f.IsArray(rule) {
|
||||
// 对于list的处理
|
||||
// 对于list的处理, 展开层级, 并自动追加到f.filterRuleList 后面
|
||||
if err = f.handleArray(rule); nil != err {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
sourceResult := gjson.Get(f.sourceData, rule.SourcePath)
|
||||
if formatVal, err = f.getValue(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 f.formatResult, err = sjson.Set(f.formatResult, rule.MapPath, formatVal); nil != err {
|
||||
if err = f.setResult(rule); nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -79,7 +80,7 @@ func (f *filter) Deal() error {
|
||||
//
|
||||
// Date : 17:48 2023/1/1
|
||||
func (f *filter) IsArray(rule MapRule) bool {
|
||||
return strings.Contains(rule.SourcePath, "[]")
|
||||
return strings.Contains(rule.SourcePath, gjson_hack.ArrayIdxTpl)
|
||||
}
|
||||
|
||||
// handleArray 处理数组(最复杂的场景)
|
||||
@ -88,33 +89,71 @@ func (f *filter) IsArray(rule MapRule) bool {
|
||||
//
|
||||
// Date : 17:41 2023/1/1
|
||||
func (f *filter) handleArray(rule MapRule) error {
|
||||
// 对于list的处理, 展开层级, 并自动追加到f.filterRuleList 后面
|
||||
var (
|
||||
err error
|
||||
)
|
||||
|
||||
sourcePathArray := strings.Split(rule.SourcePath, "[]")
|
||||
for idx, item := range sourcePathArray {
|
||||
sourcePathArray[idx] = strings.Trim(item, ".")
|
||||
expendRes := &gjson_hack.ExpendArrayResult{
|
||||
PathList: make([]string, 0),
|
||||
PathMap: map[string]string{},
|
||||
}
|
||||
mapPathArray := strings.Split(strings.TrimRight(rule.MapPath, ".[]"), "[]")
|
||||
for idx, item := range mapPathArray {
|
||||
mapPathArray[idx] = strings.Trim(item, ".")
|
||||
if err = gjson_hack.ExpandArrayPath(f.sourceData, rule.SourcePath, rule.TargetPath, expendRes); nil != err {
|
||||
return err
|
||||
}
|
||||
if len(sourcePathArray) != len(mapPathArray) {
|
||||
if len(mapPathArray) != 1 {
|
||||
return errors.New("map rule is invalid")
|
||||
}
|
||||
// 提取某一个list下的字段, 组成一个list
|
||||
res := make([]string, 0)
|
||||
if len(sourcePathArray[0]) == 0 {
|
||||
f.getAllFinalData(&res, gjson.Parse(f.sourceData).Array(), sourcePathArray[1:])
|
||||
} else {
|
||||
f.getAllFinalData(&res, gjson.Get(f.sourceData, sourcePathArray[0]).Array(), sourcePathArray[1:])
|
||||
}
|
||||
if f.formatResult, err = sjson.Set(f.formatResult, mapPathArray[0], res); nil != 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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@ -166,67 +205,3 @@ func (f *filter) Parse(receiver interface{}) error {
|
||||
}
|
||||
return json.Unmarshal(f.Byte(), receiver)
|
||||
}
|
||||
|
||||
// getValue 获取值
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:25 2022/7/4
|
||||
func (f *filter) getValue(dataType string, sourceValue gjson.Result, defaultValue string) (interface{}, error) {
|
||||
sourceValueStr := defaultValue
|
||||
if sourceValue.Exists() {
|
||||
str := sourceValue.String()
|
||||
if len(str) > 0 {
|
||||
sourceValueStr = str
|
||||
}
|
||||
}
|
||||
|
||||
strVal := wrapper.String(sourceValueStr)
|
||||
|
||||
switch dataType {
|
||||
case wrapper.DataTypeInt8:
|
||||
return strVal.ToInt8().Value, strVal.ToInt8().Err
|
||||
case wrapper.DataTypeInt16:
|
||||
return strVal.ToInt16().Value, strVal.ToInt16().Err
|
||||
case wrapper.DataTypeInt32:
|
||||
return strVal.ToInt32().Value, strVal.ToInt32().Err
|
||||
case wrapper.DataTypeInt64:
|
||||
return strVal.ToInt64().Value, strVal.ToInt64().Err
|
||||
case wrapper.DataTypeInt:
|
||||
return strVal.ToInt().Value, strVal.ToInt().Err
|
||||
case wrapper.DataTypeUint8:
|
||||
return strVal.ToUint8().Value, strVal.ToUint8().Err
|
||||
case wrapper.DataTypeUint16:
|
||||
return strVal.ToUint16().Value, strVal.ToUint16().Err
|
||||
case wrapper.DataTypeUint32:
|
||||
return strVal.ToUint32().Value, strVal.ToUint32().Err
|
||||
case wrapper.DataTypeUint64:
|
||||
return strVal.ToUint64().Value, strVal.ToUint64().Err
|
||||
case wrapper.DataTypeUint:
|
||||
return strVal.ToUint().Value, strVal.ToUint().Err
|
||||
case wrapper.DataTypeBool:
|
||||
return strVal.ToBool().Value, strVal.ToBool().Err
|
||||
case wrapper.DataTypeFloat32:
|
||||
return strVal.ToFloat64().Value, strVal.ToFloat64().Err
|
||||
case wrapper.DataTypeFloat64:
|
||||
fallthrough
|
||||
case wrapper.DataTypeFloat:
|
||||
fallthrough
|
||||
case wrapper.DataTypeDouble:
|
||||
return strVal.ToFloat64().Value, strVal.ToFloat64().Err
|
||||
case wrapper.DataTypeNumber:
|
||||
return strVal.ToNumber().Value, strVal.ToNumber().Err
|
||||
case wrapper.DataTypeString:
|
||||
return sourceValueStr, nil
|
||||
case wrapper.DataTypeAny:
|
||||
return sourceValue.Value(), nil
|
||||
case wrapper.DataTypeAnySlice:
|
||||
// 任意类型的list
|
||||
return strVal.ToAnySlice().Value, strVal.ToAnySlice().Err
|
||||
case wrapper.DataTypeObject:
|
||||
// object
|
||||
return strVal.ToObject().Value, strVal.ToObject().Err
|
||||
default:
|
||||
return nil, errors.New(dataType + " is not support!")
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
@ -37,35 +38,35 @@ func TestNewFilter(t *testing.T) {
|
||||
filterRuleList := []MapRule{
|
||||
{
|
||||
SourcePath: "base.name",
|
||||
MapPath: "user_name",
|
||||
TargetPath: "user_name",
|
||||
Required: true,
|
||||
DataType: "string",
|
||||
DefaultValue: "",
|
||||
},
|
||||
{
|
||||
SourcePath: "base.age",
|
||||
MapPath: "user_age",
|
||||
TargetPath: "user_age",
|
||||
Required: true,
|
||||
DataType: "int",
|
||||
DefaultValue: "",
|
||||
},
|
||||
{
|
||||
SourcePath: "base.height",
|
||||
MapPath: "user_height",
|
||||
TargetPath: "user_height",
|
||||
Required: true,
|
||||
DataType: "string",
|
||||
DefaultValue: "",
|
||||
},
|
||||
{
|
||||
SourcePath: "company.name",
|
||||
MapPath: "company_name",
|
||||
TargetPath: "company_name",
|
||||
Required: true,
|
||||
DataType: "string",
|
||||
DefaultValue: "",
|
||||
},
|
||||
{
|
||||
SourcePath: "company.start",
|
||||
MapPath: "company_start",
|
||||
TargetPath: "company_start",
|
||||
Required: true,
|
||||
DataType: "string",
|
||||
DefaultValue: "",
|
||||
@ -105,7 +106,7 @@ func TestNewFilterForArrayOne(t *testing.T) {
|
||||
filterRuleList := []MapRule{
|
||||
{
|
||||
SourcePath: "[].name",
|
||||
MapPath: "user_name.[]",
|
||||
TargetPath: "user_name.[]",
|
||||
Required: true,
|
||||
DataType: "string",
|
||||
DefaultValue: "",
|
||||
@ -145,7 +146,7 @@ func TestNewFilterForArrayTwo(t *testing.T) {
|
||||
filterRuleList := []MapRule{
|
||||
{
|
||||
SourcePath: "user_list.[].name",
|
||||
MapPath: "user.name_list.[]",
|
||||
TargetPath: "user.name_list.[]",
|
||||
Required: true,
|
||||
DataType: "string",
|
||||
DefaultValue: "",
|
||||
@ -158,3 +159,13 @@ func TestNewFilterForArrayTwo(t *testing.T) {
|
||||
fmt.Println(f.String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestAntMap(t *testing.T) {
|
||||
testMap := map[any]any{
|
||||
"name": "zhangde",
|
||||
1: 1,
|
||||
1.234: 2.345,
|
||||
}
|
||||
byteData, err := json.Marshal(testMap)
|
||||
fmt.Println(string(byteData), err)
|
||||
}
|
||||
|
3
gjson_hack/README.md
Normal file
3
gjson_hack/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# 对gjson库一些已知问题的pack
|
||||
|
||||
- 大数字 res.Int() 缺失精度
|
50
gjson_hack/define.go
Normal file
50
gjson_hack/define.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Package gjson_hack ...
|
||||
//
|
||||
// Description : gjson_hack ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2024-11-27 11:59
|
||||
package gjson_hack
|
||||
|
||||
import "github.com/tidwall/gjson"
|
||||
|
||||
// PathOption 路径操作的选项
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:01 2024/11/27
|
||||
type PathOption struct {
|
||||
UnfoldArray bool `json:"unfold_array"` // 展开数组
|
||||
MaxDeep int `json:"max_deep"` // 迭代最大深度, 默认 0 不限制
|
||||
OnlyFinalPath bool `json:"only_final_path"` // 仅展示最终路径
|
||||
}
|
||||
|
||||
// PathResult ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:00 2024/11/27
|
||||
type PathResult struct {
|
||||
List []string // 全部路径列表
|
||||
ValueTable map[string]gjson.Result // 路径对应的值
|
||||
}
|
||||
|
||||
const (
|
||||
ArrayIdxTpl = "{{idx}}"
|
||||
)
|
||||
|
||||
// ExpendArrayResult 展开数组的结果
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 15:46 2024/11/29
|
||||
type ExpendArrayResult struct {
|
||||
PathList []string `json:"path_list"` // 路径列表
|
||||
PathMap map[string]string `json:"path_map"` // 数据源路径 => 目标路径的处理
|
||||
}
|
||||
|
||||
const (
|
||||
SpecialKeyStart = "{{#"
|
||||
SpecialKeyEnd = "#}}"
|
||||
)
|
15
gjson_hack/error.go
Normal file
15
gjson_hack/error.go
Normal file
@ -0,0 +1,15 @@
|
||||
// Package gjson_hack ...
|
||||
//
|
||||
// Description : filter ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2024-11-30 19:14
|
||||
package gjson_hack
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrDataIsNotObject = errors.New("data is not an object")
|
||||
ErrDataIsNotArray = errors.New("data is not an array")
|
||||
)
|
363
gjson_hack/path.go
Normal file
363
gjson_hack/path.go
Normal file
@ -0,0 +1,363 @@
|
||||
// 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 = getPathKey(key.String())
|
||||
} else {
|
||||
newRootPath = rootPath + "." + getPathKey(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
|
||||
}
|
||||
|
||||
// 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}} 占位符, 说明是需要展开的数组, 根据数组的实际数据, 进行数组的逐级展开
|
||||
//
|
||||
// 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 !IsArrayItemPath(pathConfig) {
|
||||
// 不是数组模板配置, 无需展开
|
||||
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 := Get(gjson.Parse(jsonStr), 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
|
||||
}
|
||||
|
||||
// IsObject 判断是否是对象, 兼容序列化之后的对象
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:04 2024/12/1
|
||||
func IsObject(gjsonResult gjson.Result) bool {
|
||||
return gjsonResult.IsObject() || gjson.Parse(gjsonResult.String()).IsObject()
|
||||
}
|
||||
|
||||
// IsArray 判断是否为数组
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:05 2024/12/1
|
||||
func IsArray(gjsonResult gjson.Result) bool {
|
||||
return gjsonResult.IsArray() || gjson.Parse(gjsonResult.String()).IsArray()
|
||||
}
|
||||
|
||||
// Object 兼容序列化之后的对象
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:09 2024/12/1
|
||||
func Object(gjsonResult gjson.Result) gjson.Result {
|
||||
res := gjson.Parse(gjsonResult.String())
|
||||
if res.IsObject() {
|
||||
return res
|
||||
}
|
||||
return gjsonResult
|
||||
}
|
||||
|
||||
// Array ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:09 2024/12/1
|
||||
func Array(gjsonResult gjson.Result) gjson.Result {
|
||||
res := gjson.Parse(gjsonResult.String())
|
||||
if res.IsArray() {
|
||||
return res
|
||||
}
|
||||
return gjsonResult
|
||||
}
|
||||
|
||||
// Result ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:12 2024/12/1
|
||||
func Result(gjsonResult gjson.Result) gjson.Result {
|
||||
if IsObject(gjsonResult) {
|
||||
return gjsonResult
|
||||
}
|
||||
if IsArray(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
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
201
gjson_hack/path_test.go
Normal file
201
gjson_hack/path_test.go
Normal file
@ -0,0 +1,201 @@
|
||||
// Package gjson_hack ...
|
||||
//
|
||||
// Description : gjson_hack ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2024-11-27 15:52
|
||||
package gjson_hack
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func TestPath(t *testing.T) {
|
||||
mapData := map[string]any{
|
||||
"person_list": []map[string]any{
|
||||
{"name": "zhang", "age": 10},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
"company_info": map[string]any{
|
||||
"address": "Beijing",
|
||||
"email": "xxx@xxx.com",
|
||||
},
|
||||
"sex": "man",
|
||||
}
|
||||
byteData, _ := json.Marshal(mapData)
|
||||
pathRes, err := Path(string(byteData), nil)
|
||||
if nil != err {
|
||||
fmt.Println(err.Error())
|
||||
} else {
|
||||
for _, item := range pathRes.List {
|
||||
fmt.Println(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathOnlyFinallyPath(t *testing.T) {
|
||||
mapData := map[string]any{
|
||||
"person_list": []map[string]any{
|
||||
{"name": "zhang", "age": 10},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
"company_info": map[string]any{
|
||||
"address": "Beijing",
|
||||
"email": "xxx@xxx.com",
|
||||
},
|
||||
"sex": "man",
|
||||
"user_list": [][]map[string]any{
|
||||
[]map[string]any{
|
||||
{"name": "zhang", "age": 10},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
[]map[string]any{
|
||||
{"name": "zhang", "age": 20},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
[]map[string]any{
|
||||
{"name": "zhang", "age": 30},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
},
|
||||
}
|
||||
byteData, _ := json.Marshal(mapData)
|
||||
fmt.Println(gjson.GetBytes(byteData, "user_list.#.#.age"))
|
||||
fmt.Println(gjson.GetBytes(byteData, "user_list.0.0.age"))
|
||||
pathRes, err := Path(string(byteData), &PathOption{
|
||||
UnfoldArray: false,
|
||||
MaxDeep: 0,
|
||||
OnlyFinalPath: true,
|
||||
})
|
||||
if nil != err {
|
||||
fmt.Println(err.Error())
|
||||
} else {
|
||||
for _, item := range pathRes.List {
|
||||
fmt.Println(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPathOnlyFinallyPathWithUnfoldArray(t *testing.T) {
|
||||
mapData := map[string]any{
|
||||
"person_list": []map[string]any{
|
||||
{"name": "zhang", "age": 10},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
"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, "e.f": "g"},
|
||||
{"name": "li", "age": 20, "e.f": "g"},
|
||||
{"name": "wang", "age": 30, "e.f": "g"},
|
||||
},
|
||||
[]map[string]any{
|
||||
{"name": "zhang", "age": 10},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
[]map[string]any{
|
||||
{"name": "zhang", "age": 10},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
},
|
||||
}
|
||||
byteData, _ := json.Marshal(mapData)
|
||||
pathRes, err := Path(string(byteData), &PathOption{
|
||||
UnfoldArray: true,
|
||||
MaxDeep: 0,
|
||||
OnlyFinalPath: false,
|
||||
})
|
||||
if nil != err {
|
||||
fmt.Println(err.Error())
|
||||
} else {
|
||||
for _, item := range pathRes.List {
|
||||
fmt.Println(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpandArrayPath(t *testing.T) {
|
||||
mapData := map[string]any{
|
||||
"person_list": []map[string]any{
|
||||
{"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",
|
||||
"level.a.b": "deep level",
|
||||
},
|
||||
"sex": "man",
|
||||
"user_list": [][]map[string]any{
|
||||
[]map[string]any{
|
||||
{"name": "zhang", "age": 10},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
[]map[string]any{
|
||||
{"name": "zhang", "age": 10},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
[]map[string]any{
|
||||
{"name": "zhang", "age": 10},
|
||||
{"name": "li", "age": 20},
|
||||
{"name": "wang", "age": 30},
|
||||
},
|
||||
},
|
||||
}
|
||||
byteData, _ := json.Marshal(mapData)
|
||||
jsonStr := string(byteData)
|
||||
|
||||
var pathExpendRes = &ExpendArrayResult{
|
||||
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 := ""
|
||||
for _, item := range pathExpendRes.PathList {
|
||||
// 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())
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
420
gjson_hack/precision.go
Normal file
420
gjson_hack/precision.go
Normal file
@ -0,0 +1,420 @@
|
||||
// Package gjson_hack 精确地类型转换
|
||||
//
|
||||
// Description : gjson_hack ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2024-11-27 10:47
|
||||
package gjson_hack
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.zhangdeman.cn/zhangdeman/consts"
|
||||
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||
"git.zhangdeman.cn/zhangdeman/util"
|
||||
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||
"github.com/tidwall/gjson"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Number 结果转换为数字(int64 / uint64 / float64)
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:57 2024/11/27
|
||||
func Number[T int64 | uint64 | float64](gjsonResult gjson.Result, numberReceiver *T) error {
|
||||
if !gjsonResult.Exists() {
|
||||
return errors.New("gjson result not found")
|
||||
}
|
||||
if gjsonResult.Type != gjson.Number {
|
||||
return errors.New(gjsonResult.String() + " : value not a number")
|
||||
}
|
||||
if err := util.ConvertAssign(numberReceiver, gjsonResult.String()); nil != err {
|
||||
return errors.New(gjsonResult.String() + " : convert to num fail -> " + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Int 转int
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:19 2024/11/27
|
||||
func Int(gjsonResult gjson.Result) (int64, error) {
|
||||
var intResult int64
|
||||
if err := Number(gjsonResult, &intResult); nil != err {
|
||||
return 0, err
|
||||
}
|
||||
return intResult, nil
|
||||
}
|
||||
|
||||
// Uint 转为uint64
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:21 2024/11/27
|
||||
func Uint(gjsonResult gjson.Result) (uint64, error) {
|
||||
var uintResult uint64
|
||||
if err := Number(gjsonResult, &uintResult); nil != err {
|
||||
return 0, err
|
||||
}
|
||||
return uintResult, nil
|
||||
}
|
||||
|
||||
// Float64 转为float64
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:24 2024/11/27
|
||||
func Float64(gjsonResult gjson.Result) (float64, error) {
|
||||
var float64Result float64
|
||||
if err := Number(gjsonResult, &float64Result); nil != err {
|
||||
return 0, err
|
||||
}
|
||||
return float64Result, nil
|
||||
}
|
||||
|
||||
// String 获取字符串值
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:55 2024/12/1
|
||||
func String(sourceValue gjson.Result, defaultValue string) string {
|
||||
sourceValueStr := defaultValue
|
||||
if sourceValue.Exists() {
|
||||
str := sourceValue.String()
|
||||
if len(str) > 0 {
|
||||
sourceValueStr = str
|
||||
}
|
||||
}
|
||||
return sourceValueStr
|
||||
}
|
||||
|
||||
// MapAnyAny ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 17:48 2024/12/1
|
||||
func MapAnyAny(sourceValue gjson.Result) (map[string]any, error) {
|
||||
if !sourceValue.IsObject() {
|
||||
return nil, ErrDataIsNotObject
|
||||
}
|
||||
res := make(map[string]any)
|
||||
sourceValue.ForEach(func(key, value gjson.Result) bool {
|
||||
res[key.String()] = value
|
||||
return true
|
||||
})
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Any 获取任意类型的值
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:00 2024/12/1
|
||||
func Any(sourceValue gjson.Result) (any, error) {
|
||||
if !sourceValue.Exists() {
|
||||
return nil, nil
|
||||
}
|
||||
// 可能存在精度丢失, 原因 : gjson.Value 内置的转换, int64 超过一定大小会存在丢失精度问题
|
||||
if sourceValue.Num > 0 || sourceValue.Num < 0 {
|
||||
// 说明是数字
|
||||
var res float64
|
||||
if err := util.ConvertAssign(&res, sourceValue.String()); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
if sourceValue.IsObject() {
|
||||
return MapAnyAny(sourceValue)
|
||||
}
|
||||
if sourceValue.IsArray() {
|
||||
return SliceAny(sourceValue)
|
||||
}
|
||||
return sourceValue.Value(), nil
|
||||
|
||||
}
|
||||
|
||||
// getRealDataType ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:28 2024/12/1
|
||||
func getRealDataType(dataType consts.DataType, sourceValue gjson.Result) consts.DataType {
|
||||
// 指针数据类型, 转换为普通数据类型处理
|
||||
dataType = consts.DataType(strings.TrimLeft(dataType.String(), "*"))
|
||||
if dataType == consts.DataTypeAny {
|
||||
if sourceValue.IsObject() {
|
||||
dataType = consts.DataTypeMapAnyAny
|
||||
} else if sourceValue.IsArray() {
|
||||
dataType = consts.DataTypeSliceAny
|
||||
} else {
|
||||
if sourceValue.Num != 0 {
|
||||
dataType = consts.DataTypeFloat
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataType
|
||||
}
|
||||
|
||||
// SliceAny ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 17:53 2024/12/1
|
||||
func SliceAny(gjsonResult gjson.Result) ([]any, error) {
|
||||
if gjsonResult.Value() == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
strVal := strings.TrimSpace(gjsonResult.String())
|
||||
// 任意类型的list
|
||||
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
||||
// 序列化之后的数组
|
||||
sliceVal := wrapper.String(strVal).ToAnySlice()
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
// 分隔的数组
|
||||
sliceVal := wrapper.String(strVal).ToAnySlice(",")
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
|
||||
// SliceInt 获取int list
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:43 2024/12/1
|
||||
func SliceInt(gjsonResult gjson.Result) ([]int64, error) {
|
||||
if gjsonResult.Value() == nil {
|
||||
return nil, nil
|
||||
}
|
||||
strVal := strings.TrimSpace(gjsonResult.String())
|
||||
// 任意类型的list
|
||||
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
||||
// 序列化之后的数组
|
||||
sliceVal := wrapper.String(strVal).ToInt64Slice()
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
// 分隔的数组
|
||||
sliceVal := wrapper.String(strVal).ToInt64Slice(",")
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
|
||||
// SliceUint ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:58 2024/12/1
|
||||
func SliceUint(gjsonResult gjson.Result) ([]uint64, error) {
|
||||
if gjsonResult.Value() == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
strVal := strings.TrimSpace(gjsonResult.String())
|
||||
// 任意类型的list
|
||||
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
||||
// 序列化之后的数组
|
||||
sliceVal := wrapper.String(strVal).ToUint64Slice()
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
// 分隔的数组
|
||||
sliceVal := wrapper.String(strVal).ToUint64Slice(",")
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
|
||||
// SliceFloat ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:59 2024/12/1
|
||||
func SliceFloat(gjsonResult gjson.Result) ([]float64, error) {
|
||||
if gjsonResult.Value() == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
strVal := strings.TrimSpace(gjsonResult.String())
|
||||
// 任意类型的list
|
||||
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
||||
// 序列化之后的数组
|
||||
sliceVal := wrapper.String(strVal).ToFloat64Slice()
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
// 分隔的数组
|
||||
sliceVal := wrapper.String(strVal).ToFloat64Slice(",")
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
|
||||
// SliceBool ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 15:00 2024/12/1
|
||||
func SliceBool(gjsonResult gjson.Result) ([]bool, error) {
|
||||
if gjsonResult.Value() == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
strVal := strings.TrimSpace(gjsonResult.String())
|
||||
// 任意类型的list
|
||||
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
||||
// 序列化之后的数组
|
||||
sliceVal := wrapper.String(strVal).ToBoolSlice()
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
// 分隔的数组
|
||||
sliceVal := wrapper.String(strVal).ToBoolSlice(",")
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
|
||||
// SliceString ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 15:03 2024/12/1
|
||||
func SliceString(gjsonResult gjson.Result) ([]string, error) {
|
||||
if gjsonResult.Value() == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
strVal := strings.TrimSpace(gjsonResult.String())
|
||||
// 任意类型的list
|
||||
if strings.HasPrefix(strVal, "[") && strings.HasSuffix(strVal, "]") {
|
||||
// 序列化之后的数组
|
||||
sliceVal := wrapper.String(strVal).ToStringSlice()
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
// 分隔的数组
|
||||
sliceVal := wrapper.String(strVal).ToStringSlice(",")
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
}
|
||||
|
||||
// SliceMapStringAny ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 15:41 2024/12/1
|
||||
func SliceMapStringAny(gjsonResult gjson.Result) ([]map[string]any, error) {
|
||||
if gjsonResult.Value() == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
strVal := strings.TrimSpace(gjsonResult.String())
|
||||
// 任意类型的list
|
||||
if !strings.HasPrefix(strVal, "[") || !strings.HasSuffix(strVal, "]") {
|
||||
return nil, ErrDataIsNotArray
|
||||
}
|
||||
var res []map[string]any
|
||||
if err := serialize.JSON.UnmarshalWithNumber([]byte(strVal), &res); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// SliceSlice ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 17:44 2024/12/1
|
||||
func SliceSlice(gjsonResult gjson.Result) ([][]any, error) {
|
||||
if gjsonResult.Value() == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
strVal := strings.TrimSpace(gjsonResult.String())
|
||||
// 任意类型的list
|
||||
if !strings.HasPrefix(strVal, "[") || !strings.HasSuffix(strVal, "]") {
|
||||
return nil, ErrDataIsNotArray
|
||||
}
|
||||
var res [][]any
|
||||
if err := serialize.JSON.UnmarshalWithNumber([]byte(strVal), &res); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// MapStrAny 获取任意map类型的结果
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:26 2024/12/2
|
||||
func MapStrAny[T string | int64 | uint64 | bool | float64 | []any | map[string]any | any](gjsonResult gjson.Result) (map[string]T, error) {
|
||||
if !gjsonResult.IsObject() {
|
||||
return nil, ErrDataIsNotObject
|
||||
}
|
||||
var res map[string]T
|
||||
if err := serialize.JSON.UnmarshalWithNumber([]byte(gjsonResult.String()), &res); nil != err {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Value 获取指定的值
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:52 2024/12/1
|
||||
func Value(dataType consts.DataType, sourceValue gjson.Result, defaultValue any) (any, error) {
|
||||
if !sourceValue.Exists() {
|
||||
return defaultValue, nil
|
||||
}
|
||||
// 归一化处理对象、数组等
|
||||
sourceValue = Result(sourceValue)
|
||||
dataType = getRealDataType(dataType, sourceValue)
|
||||
strVal := wrapper.String(sourceValue.String())
|
||||
switch dataType {
|
||||
case consts.DataTypeInt:
|
||||
return Int(sourceValue)
|
||||
case consts.DataTypeUint:
|
||||
return Uint(sourceValue)
|
||||
case consts.DataTypeFloat:
|
||||
return Float64(sourceValue)
|
||||
case consts.DataTypeBool:
|
||||
boolVal := strVal.ToBool()
|
||||
return boolVal.Value, boolVal.Err
|
||||
case consts.DataTypeString:
|
||||
return sourceValue.String(), nil
|
||||
case consts.DataTypeAny:
|
||||
return sourceValue.Value(), nil
|
||||
case consts.DataTypeSliceAny:
|
||||
// 任意类型的list
|
||||
sliceVal := strVal.ToAnySlice()
|
||||
return sliceVal.Value, sliceVal.Err
|
||||
case consts.DataTypeSliceInt, consts.DataTypeSliceIntWithChar:
|
||||
// 任意类型的list
|
||||
return SliceInt(sourceValue)
|
||||
case consts.DataTypeSliceUint, consts.DataTypeSliceUintWithChar:
|
||||
// 任意类型的list
|
||||
return SliceUint(sourceValue)
|
||||
case consts.DataTypeSliceFloat, consts.DataTypeSliceFloatWithChar:
|
||||
// 任意类型的list
|
||||
return SliceFloat(sourceValue)
|
||||
case consts.DataTypeSliceBool, consts.DataTypeSliceBoolWithChar:
|
||||
// 任意类型的list
|
||||
return SliceBool(sourceValue)
|
||||
case consts.DataTypeSliceString, consts.DataTypeSliceStringWithChar:
|
||||
// 任意类型的list
|
||||
return SliceString(sourceValue)
|
||||
case consts.DataTypeSliceSlice:
|
||||
return SliceSlice(sourceValue)
|
||||
case consts.DataTypeMapAnyAny:
|
||||
return MapAnyAny(sourceValue)
|
||||
case consts.DataTypeSliceMapStringAny:
|
||||
return SliceMapStringAny(sourceValue)
|
||||
case consts.DataTypeMapStrInt:
|
||||
return MapStrAny[int64](sourceValue)
|
||||
case consts.DataTypeMapStrUint:
|
||||
return MapStrAny[uint64](sourceValue)
|
||||
case consts.DataTypeMapStrFloat:
|
||||
return MapStrAny[float64](sourceValue)
|
||||
case consts.DataTypeMapStrBool:
|
||||
return MapStrAny[bool](sourceValue)
|
||||
case consts.DataTypeMapStrAny:
|
||||
return MapStrAny[any](sourceValue)
|
||||
case consts.DataTypeMapStrStr:
|
||||
return MapStrAny[string](sourceValue)
|
||||
case consts.DataTypeMapStrSlice:
|
||||
return MapStrAny[[]any](sourceValue)
|
||||
default:
|
||||
return nil, errors.New("data_type = `" + dataType.String() + "` is not support!")
|
||||
}
|
||||
}
|
21
go.mod
21
go.mod
@ -1,26 +1,27 @@
|
||||
module git.zhangdeman.cn/zhangdeman/json_filter
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.5
|
||||
|
||||
require (
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701
|
||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230811070456-d6a489d5860b
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230811071513-cfc46e8d82e1
|
||||
github.com/Jeffail/gabs v1.4.0
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241125105403-cb92be844edc
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241125065949-2f87fe0cd90e
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/smartystreets/goconvey v1.8.1
|
||||
github.com/tidwall/gjson v1.16.0
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
github.com/tidwall/sjson v1.2.5
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20230811030300-6f850372c88c // indirect
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20230307094841-e437ba87af10 // indirect
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20230811032817-e6ad534a9a10 // indirect
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 // indirect
|
||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
|
||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
|
69
go.sum
69
go.sum
@ -1,28 +1,45 @@
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20230811030300-6f850372c88c h1:Dan3iSVU6XTKt8r3/qixfPHPpfLZjkYlPmaJios7wtE=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20230811030300-6f850372c88c/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240608115700-4311f44fabf6 h1:3xXT341KFAN8AzliAUJtOkyTugNpHpVXY4wDXwE0xmw=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240608115700-4311f44fabf6/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241104082108-0f97a870bbc3 h1:BiAlBJ+DuRs/xD7nDQD2JT8Oc+V+0Uwt36qZwdXGvzI=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241104082108-0f97a870bbc3/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125061350-1f5050978fc3 h1:/40XIygeSxRhPQc3/7pKGpV5hg8jwrMwh1+YiyCHdNI=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125061350-1f5050978fc3/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125065114-f919222003d9 h1:TP/M3WnGsxh0Vr6YuS1i28hw1oV//YbdCoI46PUBIA0=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125065114-f919222003d9/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701 h1:G+lGQmjMOBWGspZfijZvenGUAKpjBBrkRXLg3+GZp0U=
|
||||
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
|
||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda h1:bMD6r9gjRy7cO+T4zRQVYAesgIblBdTnhzT1vN5wjvI=
|
||||
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda/go.mod h1:dT0rmHcJ9Z9IqWeMIt7YzR88nKkNV2V3dfG0j9Q6lK0=
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20230307094841-e437ba87af10 h1:+Lg4vXFEiWVKjhUJdXuoP0AgjGT49oqJ3301STnZErk=
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20230307094841-e437ba87af10/go.mod h1:+Lc0zYF8sylRi75A7NGmObrLxugwAZa8WVpWh2eh5X0=
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20230811032817-e6ad534a9a10 h1:orhcMAKrcOajsBJCgssnb9O8YcLsPJvWuXF511gs5dc=
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20230811032817-e6ad534a9a10/go.mod h1:CzX5/WwGDTnKmewarnjkK5XcSRbgszTQTdTL3OUc/s4=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230810085948-024a0e5e963a h1:PED+zfKJdSbewYQNpcjj3uXoGDSA5+8LBGScObfuHAA=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230810085948-024a0e5e963a/go.mod h1:trYFOShINaQBvinQrH4A0G2kfL22Y2lygEcAiGDt/sc=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230811070456-d6a489d5860b h1:vnmxYrNdX6f5sEVjjkM1fIR+i32kHJ4g9DJqug9KKek=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230811070456-d6a489d5860b/go.mod h1:Yum5+tgP+Wf1GWUAyQz1Qh8Ab9m5+90GYkYdzqVs0lA=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230810085842-1e901000e998 h1:+qefkhBULVZbTGxJO4JqT1C1JQLaccJA6GLKP1qImqE=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230810085842-1e901000e998/go.mod h1:WcNcIIxTSpvjpEhfE64Ktis3q+Fw+Onw7NC2/I1U2Qs=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230811071513-cfc46e8d82e1 h1:k2iu9KgRxeroytB+N+/XapAxt1di7o2pNTISjFlYDJ8=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230811071513-cfc46e8d82e1/go.mod h1:kvjAbtGTo14gKCS0X4rxnb2sPkskHOUy2NXcx34t6Mw=
|
||||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
|
||||
github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 h1:I/wOsRpCSRkU9vo1u703slQsmK0wnNeZzsWQOGtIAG0=
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 h1:s6d4b6yY+NaK1AzoBD1pxqsuygEHQz0Oie86c45geDw=
|
||||
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4/go.mod h1:V4Dfg1v/JVIZGEKCm6/aehs8hK+Xow1dkL1yiQymXlQ=
|
||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 h1:gUDlQMuJ4xNfP2Abl1Msmpa3fASLWYkNlqDFF/6GN0Y=
|
||||
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 h1:uQcGqdzi4UdpZlp4f4FUPeBqoygP58pEKJkmN3ROsE0=
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687/go.mod h1:gf7SW2TXATgux8pfdFedMkXWv2515OtIIM/5c4atkFw=
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241108082010-42ae8fe5ebdc h1:jtdEMr/xNchJDEoCnvMr4JXT9+biYQu625Cj+dz025w=
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241108082010-42ae8fe5ebdc/go.mod h1:XqgER4jDYwskFgj2riJ9XptIjzgYWubY+Zq8iB2WkY0=
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241125105403-cb92be844edc h1:rYjlMH5Yy0G8OQgXA8qrV+fqObnB99v+6s8nbiLhzQs=
|
||||
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241125105403-cb92be844edc/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253 h1:GO3oZa5a2sqwAzGcLDJtQzmshSWRmoP7IDS8bwFqvC4=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240608120635-588df729e0d3 h1:IDzOawDhqBWHACsPKWVv/sALUj09NxrjfB2whWaovvY=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240608120635-588df729e0d3/go.mod h1:7vFN7QrHLLI/iN7ZrJSU0bw/7TyaYjVQ4+clYuIoRrY=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241106102517-46cd353dd617 h1:4rwv7bYKA4+IQgQiT8yNeM92t+fGd2tR5zD2ixpP6i8=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241106102517-46cd353dd617/go.mod h1:uEuMBRzTlUJ9k3H+PymZWPn1b48U9lJPQ+ZBWmP+O/c=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241125062526-91423fb146e0 h1:aGQADmQKTF7c8+s3acnn569sTJwjlLhhhZfQ6f4nAH0=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241125062526-91423fb146e0/go.mod h1:lvVOIrYDvCQHUzBdaOwKSrxT9ubcXQJBsafWMWu+I14=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241125065949-2f87fe0cd90e h1:/N5yXmOEH7N/h4S6nv/6os8sRenh95BXogTZ2RJI950=
|
||||
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241125065949-2f87fe0cd90e/go.mod h1:17TlhgwKTLQLIzYW/R6G39oN5FFPdsEEFDWniv+ovgA=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
|
||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
|
||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
|
||||
@ -36,16 +53,20 @@ github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY=
|
||||
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
|
||||
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
|
||||
github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
|
||||
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
|
||||
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
@ -53,8 +74,6 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
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)
|
||||
}
|
461
tool/gabs.go
461
tool/gabs.go
@ -8,19 +8,32 @@
|
||||
package json_tool
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||
"reflect"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/tidwall/sjson"
|
||||
)
|
||||
|
||||
const (
|
||||
// virtualRoot 虚拟根节点
|
||||
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<白茶清欢>
|
||||
@ -38,12 +51,45 @@ type FilterDataRule struct {
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/22 9:50 PM
|
||||
func NewDataFilter(source string, filterRule []*FilterDataRule) *DataFilter {
|
||||
return &DataFilter{
|
||||
source: source,
|
||||
filterRule: filterRule,
|
||||
hasDealDiffPath: make(map[string]string),
|
||||
func NewDataFilter(source string, filterRule []*FilterDataRule, filterOption *FilterOption) *DataFilter {
|
||||
source = fmt.Sprintf(`{"%v":%v}`, virtualRoot, source)
|
||||
if nil == filterOption {
|
||||
filterOption = &FilterOption{}
|
||||
}
|
||||
if filterOption.DebugModel && nil == filterOption.LogInstance {
|
||||
filterOption.LogInstance = os.Stdout
|
||||
log.SetOutput(filterOption.LogInstance)
|
||||
}
|
||||
df := &DataFilter{
|
||||
source: source,
|
||||
filterRule: make([]*FilterDataRule, 0),
|
||||
rewriteResult: "{}",
|
||||
filterOption: filterOption,
|
||||
}
|
||||
// 去除末尾的 .[]
|
||||
for _, item := range filterRule {
|
||||
item.MapKey = virtualRoot + "." + strings.TrimRight(item.MapKey, ".[]")
|
||||
item.SourceKey = virtualRoot + "." + strings.TrimRight(item.SourceKey, ".[]")
|
||||
mapIsArr := df.isArrPath(item.MapKey)
|
||||
if !mapIsArr {
|
||||
df.filterRule = append(df.filterRule, item)
|
||||
continue
|
||||
}
|
||||
if len(df.getArrPathList(item.SourceKey)) < len(df.getArrPathList(item.MapKey)) {
|
||||
panic("map result deep more than source data deep")
|
||||
}
|
||||
formatRes := make([]*FilterDataRule, 0)
|
||||
r, _ := df.unfoldSameDeepArr(item.SourceKey, item.MapKey, "", "")
|
||||
for _, itemUnfoldResult := range r {
|
||||
itemMapArr := strings.Split(itemUnfoldResult.MapKey, ".")
|
||||
if len(itemMapArr) != len(strings.Split(item.MapKey, ".")) {
|
||||
continue
|
||||
}
|
||||
formatRes = append(formatRes, itemUnfoldResult)
|
||||
}
|
||||
df.filterRule = append(df.filterRule, formatRes...)
|
||||
}
|
||||
return df
|
||||
}
|
||||
|
||||
// DataFilter 数据过滤
|
||||
@ -52,10 +98,10 @@ func NewDataFilter(source string, filterRule []*FilterDataRule) *DataFilter {
|
||||
//
|
||||
// Date : 2022/1/22 9:20 PM
|
||||
type DataFilter struct {
|
||||
source string
|
||||
filterRule []*FilterDataRule
|
||||
itemKeyToSlice bool
|
||||
hasDealDiffPath map[string]string
|
||||
source string
|
||||
filterRule []*FilterDataRule
|
||||
rewriteResult string // json数据重写结果
|
||||
filterOption *FilterOption // 过滤选项
|
||||
}
|
||||
|
||||
// Filter 数据过滤
|
||||
@ -64,231 +110,224 @@ type DataFilter struct {
|
||||
//
|
||||
// Date : 2022/1/22 9:36 PM
|
||||
func (df *DataFilter) Filter() (string, error) {
|
||||
df.logPrint(logLevelDebug, "source_data => ", df.source)
|
||||
var (
|
||||
jsonObject *gabs.Container
|
||||
err error
|
||||
err error
|
||||
)
|
||||
// 格式化映射规则
|
||||
df.formatRule()
|
||||
// 记录 obj => slice 的数据类型
|
||||
obg2slice := make(map[string]string)
|
||||
// 创建数据的根结点
|
||||
jsonObject = gabs.New()
|
||||
for _, item := range df.filterRule {
|
||||
// 数据源路径不识数组, 多个key写入到同一个map key, 并且map key 不是以[]结尾, 自动格式化
|
||||
// 目标位置, 是一个数组
|
||||
if df.pathIsArrayValue(item.MapKey) {
|
||||
realMapKey := strings.Trim(item.MapKey, ".[]")
|
||||
if exist := jsonObject.Exists(realMapKey); !exist {
|
||||
if _, err = jsonObject.ArrayP(realMapKey); nil != err {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
valueResult := gjson.Get(df.source, item.SourceKey)
|
||||
dataType := df.getValueType(valueResult)
|
||||
if _, exist := obg2slice[realMapKey]; !exist {
|
||||
obg2slice[realMapKey] = dataType
|
||||
}
|
||||
if dataType != obg2slice[realMapKey] {
|
||||
return "", errors.New(realMapKey + " 预期写入的字段数据类型不一致")
|
||||
}
|
||||
sourcePathArr := strings.Split(item.SourceKey, ".[].")
|
||||
mapPathArr := strings.Split(realMapKey, ".[].")
|
||||
|
||||
result := gabs.New()
|
||||
_, _ = result.ArrayP(mapPathArr[0])
|
||||
df.SetArrayData("{\""+sourcePathArr[0]+"\":"+gjson.Get(df.source, sourcePathArr[0]).String()+"}", result, sourcePathArr, mapPathArr)
|
||||
if err = jsonObject.ArrayAppend(valueResult.Value(), realMapKey); nil != err {
|
||||
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
|
||||
}
|
||||
continue
|
||||
}
|
||||
sourceSearchResult := gjson.Get(df.source, item.SourceKey)
|
||||
if !sourceSearchResult.Exists() {
|
||||
if item.WithDefault {
|
||||
if _, err = jsonObject.SetP(item.DefaultValue, item.MapKey); 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 {
|
||||
if err = df.setValue(itemRule.MapKey, df.getDataAsSlice(df.source, df.getArrPathList(itemRule.SourceKey))); nil != err {
|
||||
df.logPrint(logLevelFatal, "映射非数组, 数据源为数组, 设置失败", "source_path => "+itemRule.SourceKey, "map_path => "+itemRule.MapKey, " err => "+err.Error())
|
||||
return "", fmt.Errorf("映射的层级深度大于数据源深度, source_path => %v map_path => %v", itemRule.SourceKey, itemRule.MapKey)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if _, err = jsonObject.SetP(sourceSearchResult.Value(), item.MapKey); nil != err {
|
||||
return "", err
|
||||
|
||||
if len(mapPathArr) == len(sourcePathArr) {
|
||||
// 数组深度一致
|
||||
continue
|
||||
}
|
||||
}
|
||||
return jsonObject.String(), nil
|
||||
df.logPrint(logLevelDebug, "过滤结果", df.rewriteResult)
|
||||
return gjson.Get(df.rewriteResult, virtualRoot).String(), nil
|
||||
}
|
||||
|
||||
// UserItemToSlice 支持多个独立的字段合并到slice中
|
||||
// isArrPath 是否为数组路径
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 3:27 PM 2022/1/24
|
||||
func (df *DataFilter) UserItemToSlice() {
|
||||
df.itemKeyToSlice = true
|
||||
}
|
||||
|
||||
// getValueType 获取数据类型
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/23 12:45 AM
|
||||
func (df *DataFilter) getValueType(valueResult gjson.Result) string {
|
||||
dataTypeVal := reflect.TypeOf(valueResult.Value())
|
||||
if nil == dataTypeVal {
|
||||
return "NIL"
|
||||
}
|
||||
dataType := dataTypeVal.String()
|
||||
if strings.Contains(dataType, "int") {
|
||||
return "int64"
|
||||
}
|
||||
if strings.Contains(dataType, "float") {
|
||||
return "float64"
|
||||
}
|
||||
return dataType
|
||||
}
|
||||
|
||||
// pathIsArrayValue 判断路径是否为数组值
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/23 12:56 AM
|
||||
func (df *DataFilter) pathIsArrayValue(path string) bool {
|
||||
// Date : 16:00 2023/9/1
|
||||
func (df *DataFilter) isArrPath(path string) bool {
|
||||
return strings.Contains(path, "[]")
|
||||
}
|
||||
|
||||
// formatRule 格式化映射规则
|
||||
// setSameDeepArr 展开同深度数组的
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:43 PM 2022/1/24
|
||||
func (df *DataFilter) formatRule() {
|
||||
mapKeyCnt := make(map[string]int)
|
||||
for _, item := range df.filterRule {
|
||||
// source 为数组, map 不是
|
||||
if df.pathIsArrayValue(item.SourceKey) {
|
||||
if !df.pathIsArrayValue(item.MapKey) {
|
||||
item.MapKey = item.MapKey + ".[]"
|
||||
} else {
|
||||
// source 是数组, map也是数组, 检测数组层级匹配
|
||||
sourcePathArr := strings.Split(item.SourceKey, ".[].")
|
||||
mapPathArr := strings.Split(item.MapKey, ".[].")
|
||||
if len(sourcePathArr) == len(mapPathArr) {
|
||||
// 数组层级深度相同,无需特殊处理
|
||||
continue
|
||||
}
|
||||
// 数组层级深度不同,重新对对齐数据
|
||||
diffArr := sourcePathArr[0 : len(sourcePathArr)-len(mapPathArr)+1]
|
||||
if newPath := df.dealDiffArr(diffArr); len(newPath) > 0 {
|
||||
sourcePathArr[len(sourcePathArr)-len(mapPathArr)] = newPath
|
||||
item.SourceKey = strings.Join(sourcePathArr[len(sourcePathArr)-len(mapPathArr):], ".[].")
|
||||
}
|
||||
}
|
||||
// Date : 12:19 2023/9/2
|
||||
func (df *DataFilter) unfoldSameDeepArr(sourcePath string, mapPath string, sourceRootPath string, mapRootPath string) ([]*FilterDataRule, error) {
|
||||
df.logPrint(logLevelDebug, " 同深数组展开", sourceRootPath, mapRootPath)
|
||||
result := make([]*FilterDataRule, 0)
|
||||
if len(sourcePath) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
sourcePathArr := df.getArrPathList(sourcePath)
|
||||
mapPathArr := df.getArrPathList(mapPath)
|
||||
if 1 == len(mapPathArr) {
|
||||
sourceKey := sourceRootPath + "." + sourcePathArr[0]
|
||||
if len(sourcePathArr[0:]) > 0 {
|
||||
sourceKey = sourceRootPath + "." + strings.Join(sourcePathArr[0:], ".[].")
|
||||
}
|
||||
result = append(result, &FilterDataRule{
|
||||
SourceKey: sourceKey,
|
||||
MapKey: mapRootPath + "." + mapPathArr[0],
|
||||
DefaultValue: nil,
|
||||
WithDefault: false,
|
||||
})
|
||||
return result, nil
|
||||
}
|
||||
// 数组 展开
|
||||
for idx := 0; idx < len(mapPathArr); idx++ {
|
||||
if len(sourceRootPath) > 0 {
|
||||
sourceRootPath = fmt.Sprintf("%v.%v", sourceRootPath, sourcePathArr[idx])
|
||||
} else {
|
||||
if df.pathIsArrayValue(item.MapKey) {
|
||||
continue
|
||||
}
|
||||
// source 不是数组, map 也不是
|
||||
if !df.itemKeyToSlice {
|
||||
continue
|
||||
}
|
||||
mapKeyCnt[item.MapKey]++
|
||||
sourceRootPath = sourcePathArr[idx]
|
||||
}
|
||||
}
|
||||
// 多个source指向一个map,自动转化为list
|
||||
for _, item := range df.filterRule {
|
||||
if mapKeyCnt[item.MapKey] > 1 {
|
||||
item.MapKey = item.MapKey + ".[]"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dealDiffArr 提取数据映射关系
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:04 下午 2022/1/25
|
||||
func (df *DataFilter) dealDiffArr(diffArr []string) string {
|
||||
if len(diffArr) == 0 {
|
||||
return ""
|
||||
}
|
||||
diffArrStr := strings.Join(diffArr, ".[].")
|
||||
if _, exist := df.hasDealDiffPath[diffArrStr]; exist {
|
||||
// 已经处理过, 不再重复处理
|
||||
return df.hasDealDiffPath[diffArrStr]
|
||||
}
|
||||
|
||||
// 没处理过, 开始处理
|
||||
jsonResultList := df.getArrayData(df.source, diffArr)
|
||||
if len(jsonResultList) == 0 {
|
||||
return ""
|
||||
}
|
||||
newPath := wrapper.StringFromRandom(8, "").Value()
|
||||
var result map[string]interface{}
|
||||
_ = json.Unmarshal([]byte(df.source), &result)
|
||||
JSONObject, _ := gabs.Consume(result)
|
||||
_, _ = JSONObject.ArrayP(newPath)
|
||||
for _, item := range jsonResultList {
|
||||
if err := JSONObject.ArrayAppendP(item.Value(), newPath); nil != err {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
df.source = JSONObject.String()
|
||||
df.hasDealDiffPath[diffArrStr] = newPath
|
||||
return newPath
|
||||
}
|
||||
|
||||
// getArrayData 获取数据
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2:22 下午 2022/1/26
|
||||
func (df *DataFilter) getArrayData(source string, pathArr []string) []gjson.Result {
|
||||
if len(pathArr) == 1 {
|
||||
return gjson.Get(source, pathArr[0]).Array()
|
||||
}
|
||||
resultList := make([]gjson.Result, 0)
|
||||
dataList := gjson.Get(source, pathArr[0]).Array()
|
||||
for idx := 0; idx < len(dataList); idx++ {
|
||||
resultList = append(resultList, df.getArrayData(dataList[idx].String(), pathArr[1:])...)
|
||||
}
|
||||
return resultList
|
||||
}
|
||||
|
||||
// SetArrayData 设置数组数据
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 5:05 下午 2022/2/2
|
||||
func (df *DataFilter) SetArrayData(sourceData string, jsonObject *gabs.Container, sourcePathArr []string, mapPathArr []string) *gabs.Container {
|
||||
jsonObject = gabs.New()
|
||||
|
||||
for idx, sourcePath := range sourcePathArr {
|
||||
if idx < len(sourcePathArr)-1 {
|
||||
if !jsonObject.Exists(sourcePath) {
|
||||
_, _ = jsonObject.ArrayP(sourcePath)
|
||||
}
|
||||
}
|
||||
instance, _ := gabs.ParseJSON([]byte(sourceData))
|
||||
if !instance.Exists() {
|
||||
fmt.Println(sourcePathArr[len(sourcePathArr)-1] + " 不存在")
|
||||
if len(mapRootPath) > 0 {
|
||||
mapRootPath = fmt.Sprintf("%v.%v", mapRootPath, mapPathArr[idx])
|
||||
} else {
|
||||
dataList, _ := instance.Children()
|
||||
for _, item := range dataList {
|
||||
cItem := gabs.New()
|
||||
cItem.SetP(gjson.Get(item.String(), sourcePath).String(), mapPathArr[idx])
|
||||
jsonObject.ArrayAppendP(cItem.Data(), mapPathArr[idx])
|
||||
mapRootPath = mapPathArr[idx]
|
||||
}
|
||||
valList := gjson.Get(df.source, sourceRootPath)
|
||||
if valList.Value() == nil {
|
||||
continue
|
||||
}
|
||||
for i := 0; i < len(valList.Array()); i++ {
|
||||
result = append(result, &FilterDataRule{
|
||||
SourceKey: sourceRootPath,
|
||||
MapKey: mapRootPath,
|
||||
DefaultValue: nil,
|
||||
WithDefault: false,
|
||||
})
|
||||
r, e := df.unfoldSameDeepArr(
|
||||
strings.Join(sourcePathArr[idx+1:], "[]"),
|
||||
strings.Join(mapPathArr[idx+1:], "[]"),
|
||||
fmt.Sprintf("%v.%v", sourceRootPath, i),
|
||||
fmt.Sprintf("%v.%v", mapRootPath, i),
|
||||
)
|
||||
if nil != e {
|
||||
return nil, e
|
||||
}
|
||||
//jsonObject.ArrayAppend(jsonObject.Data())
|
||||
// fmt.Println("数据 : ", jsonObject.String())
|
||||
// jsonObject.ArrayAppendP(result.Data(), mapPathArr[idx])
|
||||
result = append(result, r...)
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// a.[].b.[].c.[].d
|
||||
// g
|
||||
// getDataAsSlice 抽取制定深度,生成list
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:17 2023/9/2
|
||||
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
|
||||
}
|
||||
|
||||
df.SetArrayData(gjson.Get(sourceData, sourcePathArr[idx]).String(), jsonObject, sourcePathArr[idx+1:], mapPathArr[idx+1:])
|
||||
// jsonObject.ArrayAppendP(v.Data(), mapPathArr[idx])
|
||||
currentPathVal := gjson.Get(sourceData, itemPath).Array()
|
||||
for _, sonItem := range currentPathVal {
|
||||
result = append(result, df.getDataAsSlice(sonItem.String(), pathList[idx:])...)
|
||||
}
|
||||
}
|
||||
fmt.Println("最终 : ", jsonObject.String())
|
||||
return jsonObject
|
||||
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"
|
||||
)
|
||||
|
285
tool/gabs_test.go
Normal file
285
tool/gabs_test.go
Normal file
@ -0,0 +1,285 @@
|
||||
// Package json_tool ...
|
||||
//
|
||||
// Description : json_tool ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2023-09-01 16:07
|
||||
package json_tool
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/serialize"
|
||||
)
|
||||
|
||||
// TestDataFilter_FilterNormalData 最基础对象
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 16:13 2023/9/1
|
||||
func TestDataFilter_FilterNormalData(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"name": "zhangdeman",
|
||||
"extra": map[string]interface{}{
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"slice": []int{1, 2, 3},
|
||||
},
|
||||
"slice": []int{1, 2, 3},
|
||||
}
|
||||
df := &DataFilter{
|
||||
source: serialize.JSON.MarshalForString(source),
|
||||
filterRule: []*FilterDataRule{
|
||||
{SourceKey: "name", MapKey: "user_name", DefaultValue: "油猴", WithDefault: true},
|
||||
{SourceKey: "extra.age", MapKey: "user_age", DefaultValue: "18", WithDefault: true},
|
||||
{SourceKey: "slice", MapKey: "user_index", DefaultValue: "[4,5,6]", WithDefault: true},
|
||||
{SourceKey: "none", MapKey: "none_default", DefaultValue: map[string]interface{}{"a": "a"}, WithDefault: true},
|
||||
{SourceKey: "extra", MapKey: "extra_object", DefaultValue: map[string]interface{}{"a": "a"}, WithDefault: true},
|
||||
},
|
||||
filterOption: &FilterOption{DebugModel: true},
|
||||
}
|
||||
fmt.Println(df.Filter())
|
||||
}
|
||||
|
||||
// TestDataFilter_getDataAsSlice 测试循环读取数据
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 22:21 2023/9/1
|
||||
func TestDataFilter_getDataAsSlice(t *testing.T) {
|
||||
data := map[string]interface{}{
|
||||
"list": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "1",
|
||||
"age": "2",
|
||||
"list_test": []interface{}{
|
||||
map[string]interface{}{
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "3",
|
||||
"age": "4",
|
||||
"list_test": []interface{}{
|
||||
map[string]interface{}{
|
||||
"a": "a1",
|
||||
"b": "b1",
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "5",
|
||||
"age": "6",
|
||||
},
|
||||
},
|
||||
}
|
||||
byteData, _ := json.Marshal(data)
|
||||
df := &DataFilter{}
|
||||
fmt.Println(df.getDataAsSlice(string(byteData), []string{"list", "name"}))
|
||||
fmt.Println(df.getDataAsSlice(string(byteData), []string{"list", "age"}))
|
||||
fmt.Println(df.getDataAsSlice(string(byteData), []string{"list", "age", "list_test", "a"}))
|
||||
fmt.Println(df.getDataAsSlice(string(byteData), []string{"list", "age", "list_test", "b"}))
|
||||
}
|
||||
|
||||
// TestDataFilter_sourceArrAndMapSingle map 非数组,数据源数组
|
||||
//
|
||||
// Author : zhangdeman001@ke.com<张德满>
|
||||
//
|
||||
// Date : 11:24 2023/9/2
|
||||
func TestDataFilter_sourceArrAndMapSingle(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"list": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "1",
|
||||
"age": "2",
|
||||
"list_test": []interface{}{
|
||||
map[string]interface{}{
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": map[string]interface{}{
|
||||
"a": "1",
|
||||
},
|
||||
"d": []int{1, 2, 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "3",
|
||||
"age": "4",
|
||||
"list_test": []interface{}{
|
||||
map[string]interface{}{
|
||||
"a": "a1",
|
||||
"b": "b1",
|
||||
"c": map[string]interface{}{
|
||||
"a": "a",
|
||||
},
|
||||
"d": []int{1, 2, 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "5",
|
||||
"age": "6",
|
||||
},
|
||||
},
|
||||
}
|
||||
df := &DataFilter{
|
||||
source: serialize.JSON.MarshalForString(source),
|
||||
filterRule: []*FilterDataRule{
|
||||
{SourceKey: "list.[].list_test.[].a", MapKey: "a_list", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].b", MapKey: "b_list", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].c", MapKey: "c_list", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].d", MapKey: "d_list", DefaultValue: "[]", WithDefault: true},
|
||||
},
|
||||
filterOption: &FilterOption{DebugModel: true},
|
||||
}
|
||||
fmt.Println(df.Filter())
|
||||
}
|
||||
|
||||
// TestDataFilter_unfoldSameDeepArr 测试展开同深度数组
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 15:42 2023/9/2
|
||||
func TestDataFilter_unfoldSameDeepArr(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"list": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "1",
|
||||
"age": "2",
|
||||
"list_test": []interface{}{
|
||||
map[string]interface{}{
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": map[string]interface{}{
|
||||
"a": "1",
|
||||
},
|
||||
"d": []int{1, 2, 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "3",
|
||||
"age": "4",
|
||||
"list_test": []interface{}{
|
||||
map[string]interface{}{
|
||||
"a": "a1",
|
||||
"b": "b1",
|
||||
"c": map[string]interface{}{
|
||||
"a": "a",
|
||||
},
|
||||
"d": []int{1, 2, 3},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"a": "a2",
|
||||
"b": "b1",
|
||||
"c": map[string]interface{}{
|
||||
"a": "a",
|
||||
},
|
||||
"d": []int{1, 2, 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "5",
|
||||
"age": "6",
|
||||
},
|
||||
},
|
||||
}
|
||||
df := &DataFilter{
|
||||
source: serialize.JSON.MarshalForString(source),
|
||||
filterRule: []*FilterDataRule{
|
||||
{SourceKey: "list.[].list_test.[].a", MapKey: "a_list.[].a.[].val", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].b", MapKey: "b_list.[].b.[].val", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].c", MapKey: "c_list.[].c.[].val", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].d", MapKey: "d_list.[].d.[].val", DefaultValue: "[]", WithDefault: true},
|
||||
},
|
||||
filterOption: &FilterOption{DebugModel: true},
|
||||
}
|
||||
r, _ := df.unfoldSameDeepArr("list.[].list_test.[].a", "a_list.[].a_not_equal_list", "", "")
|
||||
|
||||
formatRes := make([]*FilterDataRule, 0)
|
||||
for _, item := range r {
|
||||
itemMapArr := strings.Split(item.MapKey, ".")
|
||||
if len(itemMapArr) != 3 && len(itemMapArr) != 5 {
|
||||
continue
|
||||
}
|
||||
formatRes = append(formatRes, item)
|
||||
}
|
||||
fmt.Println(serialize.JSON.MarshalForString(formatRes))
|
||||
}
|
||||
|
||||
// TestDataFilter_filterSameDeepArr ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 20:41 2023/9/2
|
||||
func TestDataFilter_filterSameDeepArr(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"list": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "1",
|
||||
"age": "2",
|
||||
"list_test": []interface{}{
|
||||
map[string]interface{}{
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": map[string]interface{}{
|
||||
"a": "1",
|
||||
},
|
||||
"d": []int{1, 2, 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "3",
|
||||
"age": "4",
|
||||
"list_test": []interface{}{
|
||||
map[string]interface{}{
|
||||
"a": "a1",
|
||||
"b": "b1",
|
||||
"c": map[string]interface{}{
|
||||
"a": "a",
|
||||
},
|
||||
"d": []int{1, 2, 3},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"a": "a2",
|
||||
"b": "b1",
|
||||
"c": map[string]interface{}{
|
||||
"a": "a",
|
||||
},
|
||||
"d": []int{1, 2, 3},
|
||||
},
|
||||
},
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "5",
|
||||
"age": "6",
|
||||
},
|
||||
},
|
||||
}
|
||||
filterRuleList := []*FilterDataRule{
|
||||
{SourceKey: "name", MapKey: "user_name", DefaultValue: "油猴", WithDefault: true},
|
||||
{SourceKey: "extra.age", MapKey: "user_age", DefaultValue: "18", WithDefault: true},
|
||||
{SourceKey: "slice", MapKey: "user_index", DefaultValue: "[4,5,6]", WithDefault: true},
|
||||
{SourceKey: "none", MapKey: "none_default", DefaultValue: map[string]interface{}{"a": "a"}, WithDefault: true},
|
||||
{SourceKey: "extra", MapKey: "extra_object", DefaultValue: map[string]interface{}{"a": "a"}, WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].a", MapKey: "a_list.[].a.[].val", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].a", MapKey: "a_list.[].a_not_equal_list", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].a", MapKey: "a_list.[].a.[].val1", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].b", MapKey: "b_list.[].b.[].val", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].c", MapKey: "c_list.[].c.[].val", DefaultValue: "[]", WithDefault: true},
|
||||
{SourceKey: "list.[].list_test.[].d", MapKey: "d_list.[].d.[].val", DefaultValue: "[]", WithDefault: true},
|
||||
}
|
||||
filterOption := &FilterOption{DebugModel: true}
|
||||
|
||||
df := NewDataFilter(serialize.JSON.MarshalForString(source), filterRuleList, filterOption)
|
||||
_, _ = df.Filter()
|
||||
}
|
@ -42,15 +42,6 @@ func TestJSON(t *testing.T) {
|
||||
fmt.Println(tree.String())
|
||||
}
|
||||
|
||||
// TestType 判断数据类型断言
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 10:59 下午 2021/3/14
|
||||
func TestType(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
// TestSelect 测试动态选择字段
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
@ -127,151 +118,3 @@ func TestParse(t *testing.T) {
|
||||
byteData, _ := json.Marshal(source)
|
||||
fmt.Println(GetJSONDataStruct(string(byteData)))
|
||||
}
|
||||
|
||||
// TestParseWithType 测试获取JSON数据结构
|
||||
//
|
||||
// Author : go_developer@163.com<张德满>
|
||||
//
|
||||
// Date : 10:59 PM 2022/1/9
|
||||
func TestParseWithType(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"name": "zhangdeman",
|
||||
"extra": map[string]interface{}{
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"slice": []int{1, 2, 3},
|
||||
"obj": map[string]interface{}{
|
||||
"la": "aaaa",
|
||||
},
|
||||
},
|
||||
"slice": []int{1, 2, 3},
|
||||
"map": map[string]interface{}{"a": 1, "d": 5.5, "e": "qqq"},
|
||||
"empty_obj": map[string]interface{}{},
|
||||
"empty_list": make([]interface{}, 0),
|
||||
"table": []map[string]interface{}{
|
||||
{"name": "alex", "age": 18, "number": 1, "obj": map[string]interface{}{"enen": "en"}},
|
||||
{"name": "bob", "age": 28, "number": 2},
|
||||
},
|
||||
"two_slice": []map[string]interface{}{
|
||||
{
|
||||
"students": []map[string]interface{}{
|
||||
{
|
||||
"name": "enen",
|
||||
"age": 18,
|
||||
"score": []float64{1, 2, 3, 45},
|
||||
},
|
||||
},
|
||||
"other": []interface{}{"others"},
|
||||
"read_only": 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
byteData, _ := json.Marshal(source)
|
||||
fmt.Println(GetJSONDataStructWithType(string(byteData)))
|
||||
}
|
||||
|
||||
// TestDataFilter 测试数据过滤
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/22 10:19 PM
|
||||
func TestDataFilter(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"name": "zhangdeman",
|
||||
"extra": map[string]interface{}{
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"slice": []int{1, 2, 3},
|
||||
},
|
||||
"slice_data": []int{1, 2, 3},
|
||||
"map": map[string]interface{}{"a": 1, "b": 2, "c": 4},
|
||||
"table": []map[string]interface{}{
|
||||
{"name": "alex", "age": 18, "number": 1},
|
||||
{"name": "bob", "age": 28, "number": 2},
|
||||
{"name": "bob", "age": 28, "number": 2, "list": []int{1, 2, 3}},
|
||||
},
|
||||
}
|
||||
rule := []*FilterDataRule{
|
||||
{SourceKey: "name", MapKey: "user_name", DefaultValue: "用户姓名默认值"},
|
||||
{SourceKey: "name", MapKey: "username", DefaultValue: "用户姓名默认值"},
|
||||
{SourceKey: "name", MapKey: "user.name", DefaultValue: "用户姓名默认值"},
|
||||
{SourceKey: "extra.age", MapKey: "user.age", DefaultValue: "用户年龄默认值"},
|
||||
{SourceKey: "extra.age", MapKey: "user_age", DefaultValue: "用户年龄默认值"},
|
||||
{SourceKey: "extra.height", MapKey: "user.height", DefaultValue: "扩展高度默认值"},
|
||||
{SourceKey: "extra.height", MapKey: "user_height", DefaultValue: "扩展高度默认值"},
|
||||
{SourceKey: "table.[].name", MapKey: "slice.[].name_modify", DefaultValue: "列表姓名默认值"},
|
||||
{SourceKey: "table.[].list", MapKey: "slice.[].data_list", DefaultValue: "[\"567\",\"678\",\"789\"]"},
|
||||
}
|
||||
byteData, _ := json.Marshal(source)
|
||||
filter := NewDataFilter(string(byteData), rule)
|
||||
fmt.Println(filter.Filter())
|
||||
}
|
||||
|
||||
// TestDataFilterForObiToSlice ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022/1/23 12:06 AM
|
||||
func TestDataFilterForObiToSlice(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"name": "zhangdeman",
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"extra": map[string]interface{}{
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"slice": []int{1, 2, 3},
|
||||
},
|
||||
"slice_data": []int{1, 2, 3},
|
||||
"map": map[string]interface{}{"a": 1, "b": 2, "c": 4},
|
||||
"table": []map[string]interface{}{
|
||||
{"name": "alex", "age": 18, "number": 1},
|
||||
{"name": "bob", "age": 28, "number": 2},
|
||||
{"name": "bob", "age": 28, "number": 2, "list": []int{1, 2, 3}},
|
||||
},
|
||||
}
|
||||
rule := []*FilterDataRule{
|
||||
// {SourceKey: "name", MapKey: "slice.[]", DefaultValue: "用户姓名默认值"},
|
||||
{SourceKey: "age", MapKey: "slice", DefaultValue: "用户姓名默认值"},
|
||||
{SourceKey: "height", MapKey: "slice", DefaultValue: "用户姓名默认值"},
|
||||
}
|
||||
byteData, _ := json.Marshal(source)
|
||||
filter := NewDataFilter(string(byteData), rule)
|
||||
filter.UserItemToSlice()
|
||||
fmt.Println(filter.Filter())
|
||||
}
|
||||
|
||||
// TestDataFilterDiffArr ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:27 下午 2022/1/26
|
||||
func TestDataFilterDiffArr(t *testing.T) {
|
||||
source := map[string]interface{}{
|
||||
"name": "zhangdeman",
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"extra": map[string]interface{}{
|
||||
"age": 18,
|
||||
"height": 180,
|
||||
"slice": []int{1, 2, 3},
|
||||
},
|
||||
"slice_data": []int{1, 2, 3},
|
||||
"map": map[string]interface{}{"a": 1, "b": 2, "c": 4},
|
||||
"table": []map[string]interface{}{
|
||||
{"user_list": []interface{}{map[string]interface{}{"name": "alex", "age": 18, "number": 1}}},
|
||||
{"user_list": []interface{}{map[string]interface{}{"name": "bob", "age": 28, "number": 2}}},
|
||||
{"user_list": []interface{}{map[string]interface{}{"name": "andy", "age": 28, "number": 2}}},
|
||||
},
|
||||
}
|
||||
rule := []*FilterDataRule{
|
||||
// {SourceKey: "name", MapKey: "slice.[]", DefaultValue: "用户姓名默认值"},
|
||||
{SourceKey: "table.[].user_list.[].name", MapKey: "user_list.[].detail.name", DefaultValue: "用户姓名默认值"},
|
||||
{SourceKey: "table.[].user_list.[].age", MapKey: "user_list.[].detail.age", DefaultValue: "用户姓名默认值"},
|
||||
}
|
||||
byteData, _ := json.Marshal(source)
|
||||
filter := NewDataFilter(string(byteData), rule)
|
||||
filter.UserItemToSlice()
|
||||
filter.Filter()
|
||||
//fmt.Println()
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ package tree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.zhangdeman.cn/zhangdeman/util"
|
||||
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@ -88,7 +88,7 @@ func (g *Generate) init() error {
|
||||
fmt.Println(jsonKey, valueType, jsonValue, startIndex)
|
||||
// 创建节点, 并挂在到树上
|
||||
var newNode *Node
|
||||
if util.Array.In(g.currentNode.ValueType, []string{ValueTypeArray, ValueTypeMap}) >= 0 {
|
||||
if wrapper.ArrayType([]string{ValueTypeArray, ValueTypeMap}).Has(g.currentNode.ValueType) >= 0 {
|
||||
newNode = NewNode(jsonKey, jsonValue, valueType, g.currentNode)
|
||||
g.currentParentNode = g.currentNode
|
||||
g.currentParentNode.SonNodeList = append(g.currentParentNode.SonNodeList, newNode)
|
||||
@ -116,25 +116,26 @@ func (g *Generate) getKey(startIndex int) (string, int, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
if charStr == KeywordDoubleQuote && !hasStart {
|
||||
// 第一次遇见双引号
|
||||
startIndex++
|
||||
hasStart = true
|
||||
continue
|
||||
}
|
||||
if charStr == KeywordDoubleQuote && hasStart {
|
||||
// 第二次遇见双引号,key探寻结束
|
||||
startIndex++
|
||||
break
|
||||
if charStr == KeywordDoubleQuote {
|
||||
if !hasStart {
|
||||
// 第一次遇见双引号
|
||||
startIndex++
|
||||
hasStart = true
|
||||
continue
|
||||
} else {
|
||||
// 第二次遇见双引号,key探寻结束
|
||||
startIndex++
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasStart {
|
||||
if util.Array.In(charStr, []string{
|
||||
if wrapper.ArrayType([]string{
|
||||
KeywordDoubleQuote,
|
||||
KeywordObjectStart,
|
||||
KeywordArrayStart,
|
||||
KeywordComma,
|
||||
}) >= 0 {
|
||||
}).Has(charStr) >= 0 {
|
||||
startIndex++
|
||||
continue
|
||||
}
|
||||
@ -181,21 +182,18 @@ func (g *Generate) getValueType(startIndex int) (string, int, error) {
|
||||
hasFindColon := false
|
||||
for startIndex < len(g.jsonDataByte) {
|
||||
charStr := string(g.jsonDataByte[startIndex])
|
||||
if !hasFindColon {
|
||||
if charStr == KeywordSpace {
|
||||
// 跳过空格
|
||||
startIndex++
|
||||
continue
|
||||
}
|
||||
if charStr != KeywordSpace {
|
||||
// 非空格
|
||||
if charStr != KeywordColon {
|
||||
return "", startIndex, errors.New("value is invalid")
|
||||
}
|
||||
startIndex++
|
||||
hasFindColon = true
|
||||
break
|
||||
if charStr == KeywordSpace {
|
||||
// 跳过空格
|
||||
startIndex++
|
||||
continue
|
||||
} else {
|
||||
// 非空格
|
||||
if charStr != KeywordColon {
|
||||
return "", startIndex, errors.New("value is invalid")
|
||||
}
|
||||
startIndex++
|
||||
hasFindColon = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,13 +262,13 @@ func (g *Generate) getValue(startIndex int) (string, int, error) {
|
||||
continue
|
||||
}
|
||||
if !isStart {
|
||||
if util.Array.In(str, []string{KeywordArrayEnd, KeywordObjectEnd, KeywordComma}) >= 0 {
|
||||
if wrapper.ArrayType([]string{KeywordArrayEnd, KeywordObjectEnd, KeywordComma}).Has(str) >= 0 {
|
||||
startIndex++
|
||||
continue
|
||||
}
|
||||
}
|
||||
if isStart {
|
||||
if util.Array.In(str, []string{KeywordDoubleQuote, KeywordArrayEnd, KeywordObjectEnd, KeywordComma}) >= 0 {
|
||||
if wrapper.ArrayType([]string{KeywordDoubleQuote, KeywordArrayEnd, KeywordObjectEnd, KeywordComma}).Has(str) >= 0 {
|
||||
// 值的拼接已结束
|
||||
startIndex++
|
||||
break
|
||||
|
Reference in New Issue
Block a user