Compare commits

..

29 Commits

Author SHA1 Message Date
2e1ece4c82 gjson_read优化类型判断 2025-05-24 18:56:28 +08:00
dfae2fda76 修复Number转换BUG 2025-05-24 18:50:31 +08:00
80e62625f2 升级 gjson_hack 2025-05-24 15:26:33 +08:00
b0db389ca3 Merge pull request 'getRealDataType尅性识别优化 + Value 泛解析支持更多数据类型' (#11) from feature/bug_fix into master
Reviewed-on: #11
2025-05-06 17:08:24 +08:00
a0c2fb37e3 getRealType适配未输入数据类型的情况 2025-05-06 17:07:45 +08:00
c403047e9f getRealDataType尅性识别优化 + Value 泛解析支持更多数据类型 2025-05-06 17:04:20 +08:00
777a5cb93c 所有操作加锁 2025-05-06 16:02:14 +08:00
691bee91a5 sjson_write支持删除数据 2025-05-06 15:42:24 +08:00
c7ce590e3b add bool support 2025-05-06 14:43:22 +08:00
6c2c68c53e Merge pull request '升级json操作, 升级为面向接口实现' (#10) from feature/upgrade_get_set into master
Reviewed-on: #10
2025-05-06 14:14:30 +08:00
38b2d74f35 remove debug code 2025-05-06 14:14:18 +08:00
a28bc364e4 优化filter逻辑 2025-05-06 14:10:38 +08:00
47726c20b8 SJsonWrite设置数据时, 支持做map合并 2025-05-06 12:39:48 +08:00
042aad254b IJsonRead支持Value, 泛读取数据 2025-05-06 12:22:26 +08:00
1124ff6a33 增加基于sjson实现的IJsonWrite 2025-05-06 12:07:58 +08:00
8489acbef8 增加基于gsjon实现的JsonRead 2025-05-06 11:51:50 +08:00
761058f8fe 增加IJsonRead与IJsonWrite接口约束 2025-05-06 10:58:20 +08:00
587a9bbe9d Merge pull request 'update go mod' (#9) from feature/upgrade into master
Reviewed-on: #9
2025-03-29 16:02:13 +08:00
50a8474e4d update go mod 2025-03-29 15:49:49 +08:00
28fbd1e820 fix 2025-03-29 15:47:56 +08:00
bbe5eb089f update go mod 2025-03-29 15:46:31 +08:00
786c03293a upgrade wrapper 2025-03-21 18:30:29 +08:00
b8c8c9d433 Merge pull request 'gjson+sjson hack升级' (#8) from feature/sjson_hack into master
Reviewed-on: #8
2024-12-05 18:50:07 +08:00
96ff376470 sjson支持设置key中包含 . 字符 2024-12-05 18:49:04 +08:00
f61f9b28b1 增加兼容的GetMany方法 2024-12-05 16:34:29 +08:00
f88826411f add test 2024-12-05 16:14:10 +08:00
df6e554d03 修复Get方法的BUG + 升级基于实际数据展开数据组真实路径的方法ExpandArrayPath 2024-12-05 16:09:18 +08:00
48639ba59a gjson读取参数支持key名称中包含. 2024-12-04 20:50:13 +08:00
355144b623 优化Result 2024-12-04 20:15:42 +08:00
14 changed files with 722 additions and 134 deletions

38
abstract/json_read.go Normal file
View File

@ -0,0 +1,38 @@
// Package abstract ...
//
// Description : abstract ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-05-06 10:42
package abstract
// IJsonRead json数据读取接口约束
type IJsonRead interface {
// Exist 指定路径是否存在
Exist(dataPath string) bool
// IsNil 指定路径是否为nil
IsNil(dataPath string) bool
// Type 路径数据类型
Type(dataPath string) string
// Int 转换为int类型
Int(dataPath string) (int64, error)
// Uint 转换为uint类型
Uint(dataPath string) (uint64, error)
// Float 转换为float类型
Float(dataPath string) (float64, error)
// String 转换为string类型
String(dataPath string) (string, error)
// Bool 转换为bool类型
Bool(dataPath string) (bool, error)
// Map 转换为map
Map(dataPath string) (map[string]any, error)
// MapWithReceiver 通过指针接收
MapWithReceiver(dataPath string, receiver any) error
// Array 转换为数组
Array(dataPath string) ([]any, error)
// ArrayWithReceiver 通过指针接收
ArrayWithReceiver(dataPath string, receiver any) error
// Value 自适应类型数据读取
Value(dataPath string, dataType string, defaultValue any) (any, error)
}

26
abstract/json_write.go Normal file
View File

@ -0,0 +1,26 @@
// Package abstract ...
//
// Description : abstract ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-05-06 10:53
package abstract
// IJsonWrite json数据写入
type IJsonWrite interface {
// Set 设置一个路径的值
Set(dataPath string, data any) error
// Delete 删除一个路径
Delete(dataPath string) error
// Result 最终结果以字符串形式返回
Result() string
// Map 最终结果以map返回
Map() (map[string]any, error)
// MapWithReceiver 外部指针接收返回值
MapWithReceiver(receiver any) error
// Array 最终结果以数组返回
Array() ([]any, error)
// ArrayWithReceiver 外部指针接收返回值
ArrayWithReceiver(receiver any) error
}

View File

@ -8,19 +8,31 @@
package filter
import (
"encoding/json"
"fmt"
"reflect"
"git.zhangdeman.cn/zhangdeman/json_filter/abstract"
"git.zhangdeman.cn/zhangdeman/json_filter/implement"
"strings"
"git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack"
"git.zhangdeman.cn/zhangdeman/serialize"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"errors"
"git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack"
"github.com/tidwall/gjson"
)
func NewFilterWithJson(sourceData string, filterRuleList []MapRule, jsonRead abstract.IJsonRead, jsonWrite abstract.IJsonWrite) *filter {
if nil == jsonRead {
jsonRead = implement.NewGjsonRead(sourceData)
}
if nil == jsonWrite {
jsonWrite = implement.NewSjsonWrite()
}
return &filter{
jsonRaad: jsonRead,
jsonWrite: jsonWrite,
sourceData: sourceData,
filterRuleList: filterRuleList,
}
}
// NewFilter 过滤器实例
//
// Author : go_developer@163.com<白茶清欢>
@ -29,7 +41,8 @@ import (
func NewFilter(sourceData string, filterRuleList []MapRule) *filter {
return &filter{
sourceData: sourceData,
formatResult: "{}",
jsonRaad: implement.NewGjsonRead(sourceData),
jsonWrite: implement.NewSjsonWrite(),
filterRuleList: filterRuleList,
}
}
@ -40,8 +53,9 @@ func NewFilter(sourceData string, filterRuleList []MapRule) *filter {
//
// Date : 11:58 2022/7/4
type filter struct {
jsonRaad abstract.IJsonRead
jsonWrite abstract.IJsonWrite
sourceData string
formatResult string
filterRuleList []MapRule
}
@ -126,33 +140,10 @@ func (f *filter) setResult(rule MapRule) error {
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 formatVal, err = f.jsonRaad.Value(rule.SourcePath, rule.DataType.String(), rule.DefaultValue); nil != err {
return fmt.Errorf("%s = %v can not convert to %s : %s", rule.SourcePath, gjson.Get(f.sourceData, rule.SourcePath).String(), 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 {
if err = f.jsonWrite.Set(rule.TargetPath, formatVal); nil != err {
return err
}
return nil
@ -182,7 +173,7 @@ func (f *filter) getAllFinalData(res *[]string, resultList []gjson.Result, pathA
//
// Date : 21:18 2022/12/31
func (f *filter) String() string {
return f.formatResult
return f.jsonWrite.Result()
}
// Byte 获取格式化之后的字节数组
@ -199,9 +190,10 @@ func (f *filter) Byte() []byte {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:20 2022/12/31
func (f *filter) Parse(receiver interface{}) error {
func (f *filter) Parse(receiver any) error {
if nil == receiver {
return errors.New("receiver is nil")
}
return json.Unmarshal(f.Byte(), receiver)
return f.jsonWrite.MapWithReceiver(receiver)
// return json.Unmarshal(f.Byte(), receiver)
}

View File

@ -31,7 +31,7 @@ type PathResult struct {
}
const (
ArrayIdxTpl = "{{idx}}"
ArrayIdxTpl = "[]"
)
// ExpendArrayResult 展开数组的结果
@ -43,3 +43,8 @@ type ExpendArrayResult struct {
PathList []string `json:"path_list"` // 路径列表
PathMap map[string]string `json:"path_map"` // 数据源路径 => 目标路径的处理
}
const (
SpecialKeyStart = "{{#"
SpecialKeyEnd = "#}}"
)

View File

@ -7,9 +7,9 @@
// 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")
ErrDataPathNotFound = "data_path_not_found"
ErrDataIsNotObject = "data_is_not_object"
ErrDataIsNotArray = "data_is_not_an_array"
ErrDataTypeIsNotSupport = "data_type_is_not_support"
)

View File

@ -66,9 +66,9 @@ func doExpandPath(gjsonResult gjson.Result, rootPath string, hasChildren bool, p
gjsonResult.ForEach(func(key, value gjson.Result) bool {
newRootPath := ""
if len(rootPath) == 0 {
newRootPath = key.String()
newRootPath = getPathKey(key.String())
} else {
newRootPath = rootPath + "." + key.String()
newRootPath = rootPath + "." + getPathKey(key.String())
}
if value.IsArray() || value.IsObject() {
if !pathOption.OnlyFinalPath {
@ -125,9 +125,35 @@ func doExpandPath(gjsonResult gjson.Result, rootPath string, hasChildren bool, p
return
}
// getPathKey ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:54 2024/12/4
func getPathKey(key string) string {
if !strings.Contains(key, ".") {
// 非特殊key
return key
}
if IsSpecialKey(key) {
// 已经是special key
return key
}
return SpecialKeyStart + key + SpecialKeyEnd
}
// IsArrayItemPath 是否为数组子项路径
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:49 2024/12/5
func IsArrayItemPath(path string) bool {
return strings.Contains(path, ArrayIdxTpl)
}
// ExpandArrayPath 根据真实数据展开数组路径
//
// 路径中若是包含 {{idx}} 占位符, 说明是需要展开的数组, 根据数组的时机数据, 进行数组的逐级展开
// 路径中若是包含 {{idx}} 占位符, 说明是需要展开的数组, 根据数组的实际数据, 进行数组的逐级展开
//
// Author : go_developer@163.com<白茶清欢>
//
@ -145,7 +171,7 @@ func ExpandArrayPath(jsonStr string, pathConfig string, mapConfig string, expend
if len(mapConfig) == 0 {
mapConfig = pathConfig
}
if !strings.Contains(pathConfig, ArrayIdxTpl) {
if !IsArrayItemPath(pathConfig) {
// 不是数组模板配置, 无需展开
expendArrayResult.PathList = append(expendArrayResult.PathList, pathConfig)
expendArrayResult.PathMap[pathConfig] = mapConfig
@ -163,7 +189,7 @@ func ExpandArrayPath(jsonStr string, pathConfig string, mapConfig string, expend
return errors.New("mapConfig depth not equal pathConfig deep")
}
valueResult := gjson.Parse(jsonStr).Get(pathConfigArr[0])
valueResult := Get(gjson.Parse(jsonStr), pathConfigArr[0])
if !valueResult.Exists() {
// 路径不存在, 无需设置具体值
return nil
@ -240,5 +266,98 @@ func Result(gjsonResult gjson.Result) gjson.Result {
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)
}

View File

@ -12,8 +12,6 @@ import (
"fmt"
"testing"
"github.com/tidwall/sjson"
"github.com/tidwall/gjson"
)
@ -98,13 +96,14 @@ func TestPathOnlyFinallyPathWithUnfoldArray(t *testing.T) {
"company_info": map[string]any{
"address": "Beijing",
"email": "xxx@xxx.com",
"a.b": "cd",
},
"sex": "man",
"user_list": [][]map[string]any{
[]map[string]any{
{"name": "zhang", "age": 10},
{"name": "li", "age": 20},
{"name": "wang", "age": 30},
{"name": "zhang", "age": 10, "e.f": "g"},
{"name": "li", "age": 20, "e.f": "g"},
{"name": "wang", "age": 30, "e.f": "g"},
},
[]map[string]any{
{"name": "zhang", "age": 10},
@ -136,13 +135,14 @@ func TestPathOnlyFinallyPathWithUnfoldArray(t *testing.T) {
func TestExpandArrayPath(t *testing.T) {
mapData := map[string]any{
"person_list": []map[string]any{
{"name": "zhang", "age": 10},
{"name": "li", "age": 20},
{"name": "wang", "age": 30},
{"name": "zhang", "age": 10, "a.b": "people_name"},
{"name": "li", "age": 20, "a.b": "people_name"},
{"name": "wang", "age": 30, "a.b": "people_name"},
},
"company_info": map[string]any{
"address": "Beijing",
"email": "xxx@xxx.com",
"address": "Beijing",
"email": "xxx@xxx.com",
"level.a.b": "deep level",
},
"sex": "man",
"user_list": [][]map[string]any{
@ -170,12 +170,32 @@ func TestExpandArrayPath(t *testing.T) {
PathList: nil,
PathMap: nil,
}
ExpandArrayPath(jsonStr, "company_info.{{#level.a.b#}}", "company_info.a-b", pathExpendRes)
ExpandArrayPath(jsonStr, "person_list.{{idx}}.{{#a.b#}}", "person_list.{{idx}}.a-b", pathExpendRes)
ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.age", "a.{{idx}}.{{idx}}.b", pathExpendRes)
ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.name", "e.{{idx}}.{{idx}}.c", pathExpendRes)
ExpandArrayPath(jsonStr, "user_list.{{idx}}.{{idx}}.sex", "f.{{idx}}.{{idx}}.c", pathExpendRes)
res := ""
// res := ""
for _, item := range pathExpendRes.PathList {
res, _ = sjson.Set(res, pathExpendRes.PathMap[item], gjson.Get(jsonStr, item).Value())
// fmt.Println(item, pathExpendRes.PathMap[item])
fmt.Println(item, pathExpendRes.PathMap[item], Get(gjson.Parse(jsonStr), item).String())
// res, _ = sjson.Set(res, pathExpendRes.PathMap[item], Get(gjson.Parse(jsonStr), item).Value())
}
fmt.Println(res)
}
func TestGet(t *testing.T) {
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())
}

View File

@ -10,6 +10,7 @@ package gjson_hack
import (
"errors"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/exception"
"git.zhangdeman.cn/zhangdeman/serialize"
"git.zhangdeman.cn/zhangdeman/util"
"git.zhangdeman.cn/zhangdeman/wrapper"
@ -22,7 +23,7 @@ import (
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:57 2024/11/27
func Number[T int64 | uint64 | float64](gjsonResult gjson.Result, numberReceiver *T) error {
func Number(gjsonResult gjson.Result, numberReceiver any) error {
if !gjsonResult.Exists() {
return errors.New("gjson result not found")
}
@ -40,8 +41,8 @@ func Number[T int64 | uint64 | float64](gjsonResult gjson.Result, numberReceiver
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:19 2024/11/27
func Int(gjsonResult gjson.Result) (int64, error) {
var intResult int64
func Int[T int8 | int16 | int32 | int64 | int](gjsonResult gjson.Result) (T, error) {
var intResult T
if err := Number(gjsonResult, &intResult); nil != err {
return 0, err
}
@ -53,25 +54,25 @@ func Int(gjsonResult gjson.Result) (int64, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:21 2024/11/27
func Uint(gjsonResult gjson.Result) (uint64, error) {
var uintResult uint64
func Uint[T uint8 | uint16 | uint32 | uint64 | uint](gjsonResult gjson.Result) (T, error) {
var uintResult T
if err := Number(gjsonResult, &uintResult); nil != err {
return 0, err
}
return uintResult, nil
}
// Float64 转为float64
// Float 转为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 {
func Float[T float32 | float64](gjsonResult gjson.Result) (T, error) {
var floatResult T
if err := Number(gjsonResult, &floatResult); nil != err {
return 0, err
}
return float64Result, nil
return floatResult, nil
}
// String 获取字符串值
@ -96,8 +97,11 @@ func String(sourceValue gjson.Result, defaultValue string) string {
//
// Date : 17:48 2024/12/1
func MapAnyAny(sourceValue gjson.Result) (map[string]any, error) {
if !sourceValue.Exists() {
return nil, exception.New(ErrDataPathNotFound, nil, "data path not found")
}
if !sourceValue.IsObject() {
return nil, ErrDataIsNotObject
return nil, exception.New(ErrDataIsNotObject, nil)
}
res := make(map[string]any)
sourceValue.ForEach(func(key, value gjson.Result) bool {
@ -117,13 +121,33 @@ func Any(sourceValue gjson.Result) (any, error) {
return nil, nil
}
// 可能存在精度丢失, 原因 : gjson.Value 内置的转换, int64 超过一定大小会存在丢失精度问题
if sourceValue.Num > 0 || sourceValue.Num < 0 {
if sourceValue.Type == gjson.Number {
// 说明是数字
var res float64
if err := util.ConvertAssign(&res, sourceValue.String()); nil != err {
return nil, err
if strings.Contains(sourceValue.String(), ".") {
// 小数
var res float64
if err := Number(sourceValue, &res); nil != err {
return nil, err
}
return res, nil
} else {
// 整数
if strings.HasPrefix(sourceValue.String(), "-") {
// 负数
var res int64
if err := Number(sourceValue, &res); nil != err {
return nil, err
}
return res, nil
} else {
// 正数
var res uint64
if err := Number(sourceValue, &res); nil != err {
return nil, err
}
return res, nil
}
}
return res, nil
}
if sourceValue.IsObject() {
return MapAnyAny(sourceValue)
@ -143,14 +167,21 @@ func Any(sourceValue gjson.Result) (any, error) {
func getRealDataType(dataType consts.DataType, sourceValue gjson.Result) consts.DataType {
// 指针数据类型, 转换为普通数据类型处理
dataType = consts.DataType(strings.TrimLeft(dataType.String(), "*"))
if dataType == consts.DataTypeAny {
// 没指定数据类型或者数据类型是any
if dataType == consts.DataTypeAny || dataType == "" {
if sourceValue.IsObject() {
dataType = consts.DataTypeMapAnyAny
} else if sourceValue.IsArray() {
dataType = consts.DataTypeSliceAny
} else if sourceValue.IsBool() {
dataType = consts.DataTypeBool
} else {
if sourceValue.Num != 0 {
dataType = consts.DataTypeFloat
if sourceValue.Type == gjson.Number {
dataType = consts.DataTypeFloat64
} else if sourceValue.Type == gjson.String {
dataType = consts.DataTypeString
} else {
dataType = consts.DataTypeAny
}
}
}
@ -253,7 +284,6 @@ 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, "]") {
@ -300,8 +330,8 @@ func SliceMapStringAny(gjsonResult gjson.Result) ([]map[string]any, error) {
strVal := strings.TrimSpace(gjsonResult.String())
// 任意类型的list
if !strings.HasPrefix(strVal, "[") || !strings.HasSuffix(strVal, "]") {
return nil, ErrDataIsNotArray
if !gjsonResult.IsArray() {
return nil, exception.New(ErrDataIsNotArray, nil)
}
var res []map[string]any
if err := serialize.JSON.UnmarshalWithNumber([]byte(strVal), &res); nil != err {
@ -322,8 +352,8 @@ func SliceSlice(gjsonResult gjson.Result) ([][]any, error) {
strVal := strings.TrimSpace(gjsonResult.String())
// 任意类型的list
if !strings.HasPrefix(strVal, "[") || !strings.HasSuffix(strVal, "]") {
return nil, ErrDataIsNotArray
if !gjsonResult.IsArray() {
return nil, exception.New(ErrDataIsNotArray, nil)
}
var res [][]any
if err := serialize.JSON.UnmarshalWithNumber([]byte(strVal), &res); nil != err {
@ -339,7 +369,7 @@ func SliceSlice(gjsonResult gjson.Result) ([][]any, error) {
// 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
return nil, exception.New(ErrDataIsNotArray, nil)
}
var res map[string]T
if err := serialize.JSON.UnmarshalWithNumber([]byte(gjsonResult.String()), &res); nil != err {
@ -363,17 +393,36 @@ func Value(dataType consts.DataType, sourceValue gjson.Result, defaultValue any)
strVal := wrapper.String(sourceValue.String())
switch dataType {
case consts.DataTypeInt:
return Int(sourceValue)
return Int[int](sourceValue)
case consts.DataTypeInt8:
return Int[int8](sourceValue)
case consts.DataTypeInt16:
return Int[int16](sourceValue)
case consts.DataTypeInt32:
return Int[int32](sourceValue)
case consts.DataTypeInt64:
return Int[int64](sourceValue)
case consts.DataTypeUint:
return Uint(sourceValue)
case consts.DataTypeFloat:
return Float64(sourceValue)
return Uint[uint](sourceValue)
case consts.DataTypeUint8:
return Uint[uint8](sourceValue)
case consts.DataTypeUint16:
return Uint[uint16](sourceValue)
case consts.DataTypeUint32:
return Uint[uint32](sourceValue)
case consts.DataTypeUint64:
return Uint[uint64](sourceValue)
case consts.DataTypeFloat64:
return Float[float64](sourceValue)
case consts.DataTypeFloat32:
return Float[float32](sourceValue)
case consts.DataTypeBool:
boolVal := strVal.ToBool()
return boolVal.Value, boolVal.Err
case consts.DataTypeString:
return sourceValue.String(), nil
case consts.DataTypeAny:
// 经过getRealDataType类型处理后依旧是any,不考虑精度问题
return sourceValue.Value(), nil
case consts.DataTypeSliceAny:
// 任意类型的list
@ -415,6 +464,6 @@ func Value(dataType consts.DataType, sourceValue gjson.Result, defaultValue any)
case consts.DataTypeMapStrSlice:
return MapStrAny[[]any](sourceValue)
default:
return nil, errors.New("data_type = `" + dataType.String() + "` is not support!")
return nil, exception.New(ErrDataTypeIsNotSupport, map[string]any{"data_type": dataType.String()})
}
}

15
go.mod
View File

@ -1,15 +1,15 @@
module git.zhangdeman.cn/zhangdeman/json_filter
go 1.21
go 1.23.0
toolchain go1.21.5
toolchain go1.24.3
require (
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125100843-b1b286c7a701
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995
git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20230731062340-983985c12eda
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241125105403-cb92be844edc
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241125065949-2f87fe0cd90e
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740
github.com/pkg/errors v0.9.1
github.com/smartystreets/goconvey v1.8.1
github.com/tidwall/gjson v1.18.0
@ -18,15 +18,16 @@ require (
)
require (
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 // indirect
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab // indirect
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // 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
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mozillazg/go-pinyin v0.20.0 // indirect
github.com/sbabiv/xml2map v1.2.1 // indirect
github.com/smarty/assertions v1.15.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/tidwall/match v1.1.1 // indirect

56
go.sum
View File

@ -1,41 +1,25 @@
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/consts v0.0.0-20250321102241-d6e86b64f7ca h1:uxjzbY5fDozjyK6jkoQtuQouVTcVfXjbe3chARYSjRM=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250321102241-d6e86b64f7ca/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c h1:cl3gQGXQpJ8ugDs0C/hQLfcvF4lGBm5BeABLvROFDoM=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250328040304-7e4a6f9f148c/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995 h1:LmPRAf0AsxRVFPibdpZR89ajlsz8hof2IvMMyTqiEq4=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250425024726-cc17224cb995/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
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-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/exception v0.0.0-20250510123912-a0d52fc093ab h1:O0XaAKKb8qrjcjewonmKfnRsMFoCfJF+tUv6RfhRe94=
git.zhangdeman.cn/zhangdeman/exception v0.0.0-20250510123912-a0d52fc093ab/go.mod h1:Voc8J4ordx7nuMWpgACXXZULQy7ZIuBzcEIoS8VnDIw=
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/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9 h1:/GLQaFoLb+ciHOtAS2BIyPNnf4O5ME3AC5PUaJY9kfs=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20250504055908-8d68e6106ea9/go.mod h1:ABJ655C5QenQNOzf7LjCe4sSB52CXvaWLX2Zg4uwDJY=
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=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 h1:zPUoylfJTbc0EcxW+NEzOTBmoeFZ2I/rLFBnEzxb4Wk=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740/go.mod h1:1ct92dbVc49pmXusA/iGfcQUJzcYmJ+cjAhgc3sDv1I=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.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=
@ -54,17 +38,17 @@ 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/sbabiv/xml2map v1.2.1 h1:1lT7t0hhUvXZCkdxqtq4n8/ZCnwLWGq4rDuDv5XOoFE=
github.com/sbabiv/xml2map v1.2.1/go.mod h1:2TPoAfcaM7+Sd4iriPvzyntb2mx7GY+kkQpB/GQa/eo=
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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.14.2/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=

142
implement/gjson_read.go Normal file
View File

@ -0,0 +1,142 @@
// Package implement ...
//
// Description : implement ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-05-06 11:00
package implement
import (
"errors"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/json_filter/abstract"
"git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack"
"git.zhangdeman.cn/zhangdeman/serialize"
"github.com/tidwall/gjson"
"strings"
)
// NewGjsonRead ...
func NewGjsonRead(sourceData string) abstract.IJsonRead {
return &gjsonRead{
sourceData: sourceData,
gjsonResult: gjson.Parse(sourceData),
}
}
type gjsonRead struct {
sourceData string
gjsonResult gjson.Result
}
func (g *gjsonRead) Exist(dataPath string) bool {
return g.gjsonResult.Get(dataPath).Exists()
}
func (g *gjsonRead) IsNil(dataPath string) bool {
return g.gjsonResult.Get(dataPath).Value() == nil
}
func (g *gjsonRead) Type(dataPath string) string {
pathRes := g.gjsonResult.Get(dataPath)
if pathRes.IsObject() { // map
return consts.DataTypeMapStrAny.String()
}
if pathRes.IsArray() { // slice
return consts.DataTypeSliceAny.String()
}
if pathRes.IsBool() { // bool
return consts.DataTypeBool.String()
}
dataType := pathRes.Type
switch dataType {
case gjson.String:
return consts.DataTypeString.String()
case gjson.Number:
valStr := pathRes.String()
if strings.Contains(valStr, ".") {
return consts.DataTypeFloat64.String()
}
if strings.HasPrefix(valStr, "-") {
return consts.DataTypeInt64.String()
}
return consts.DataTypeUint64.String()
case gjson.Null:
return consts.DataTypeAny.String()
case gjson.True, gjson.False:
return consts.DataTypeBool.String()
}
return consts.DataTypeAny.String() // any类型兜底
}
func (g *gjsonRead) Int(dataPath string) (int64, error) {
return gjson_hack.Int[int64](g.gjsonResult.Get(dataPath))
}
func (g *gjsonRead) Uint(dataPath string) (uint64, error) {
return gjson_hack.Uint[uint64](g.gjsonResult.Get(dataPath))
}
func (g *gjsonRead) Float(dataPath string) (float64, error) {
return gjson_hack.Float[float64](g.gjsonResult.Get(dataPath))
}
func (g *gjsonRead) Bool(dataPath string) (bool, error) {
res := g.gjsonResult.Get(dataPath)
if !res.IsBool() {
return false, errors.New(dataPath + ": is not a bool")
}
return res.Bool(), nil
}
func (g *gjsonRead) String(dataPath string) (string, error) {
if !g.Exist(dataPath) {
return "", errors.New(dataPath + ": not found")
}
return g.gjsonResult.Get(dataPath).String(), nil
}
func (g *gjsonRead) Map(dataPath string) (map[string]any, error) {
var (
err error
dataMap map[string]any
)
if err = g.MapWithReceiver(dataPath, &dataMap); nil != err {
return map[string]any{}, err
}
return dataMap, nil
}
func (g *gjsonRead) MapWithReceiver(dataPath string, receiver any) error {
strVal, err := g.String(dataPath)
if nil != err {
return err
}
return serialize.JSON.UnmarshalWithNumber([]byte(strVal), receiver)
}
func (g *gjsonRead) Array(dataPath string) ([]any, error) {
var (
err error
dataArr []any
)
if err = g.ArrayWithReceiver(dataPath, &dataArr); nil != err {
return []any{}, err
}
return dataArr, nil
}
func (g *gjsonRead) ArrayWithReceiver(dataPath string, receiver any) error {
strVal, err := g.String(dataPath)
if nil != err {
return err
}
return serialize.JSON.UnmarshalWithNumber([]byte(strVal), receiver)
}
func (g *gjsonRead) Value(dataPath string, dataType string, defaultValue any) (any, error) {
if len(dataType) == 0 {
dataType = g.Type(dataPath)
}
return gjson_hack.Value(consts.DataType(dataType), g.gjsonResult.Get(dataPath), defaultValue)
}

128
implement/sjson_write.go Normal file
View File

@ -0,0 +1,128 @@
// Package implement ...
//
// Description : implement ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2025-05-06 11:53
package implement
import (
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/json_filter/abstract"
"git.zhangdeman.cn/zhangdeman/serialize"
"github.com/tidwall/sjson"
"reflect"
"sync"
)
func NewSjsonWrite() abstract.IJsonWrite {
return &SjsonWrite{
res: "",
l: &sync.RWMutex{},
}
}
type SjsonWrite struct {
res string
l *sync.RWMutex
}
func (s *SjsonWrite) Delete(dataPath string) error {
var (
err error
)
s.l.Lock()
defer s.l.Unlock()
if s.res, err = sjson.Delete(s.res, dataPath); nil != err {
return err
}
return nil
}
func (s *SjsonWrite) Set(dataPath string, data any) error {
var (
err error
)
s.l.Lock()
defer s.l.Unlock()
existResRead := NewGjsonRead(s.res)
if !existResRead.Exist(dataPath) || data == nil {
// 路径不存在
if s.res, err = sjson.Set(s.res, dataPath, data); nil != err {
return err
}
return nil
}
// 路径已存在, 判断是否为map
if existResRead.Type(dataPath) != consts.DataTypeMapStrAny.String() {
if s.res, err = sjson.Set(s.res, dataPath, data); nil != err {
return err
}
return nil
}
// 判断data是否为map
dataType := reflect.TypeOf(data)
if dataType.Kind() == reflect.Ptr {
dataType = dataType.Elem()
}
if dataType.Kind() != reflect.Struct && dataType.Kind() != reflect.Map {
// 既不是map, 也不是struct
if s.res, err = sjson.Set(s.res, dataPath, data); nil != err {
return err
}
return nil
}
// 路径已存在, 已存在数据为map, 且要设置的数据也为map, 进行数据合并
mergeDataMap := map[string]any{}
existMapVal := map[string]any{}
if existMapVal, err = existResRead.Map(dataPath); nil != err {
return err
}
// 合并输入数据
if err = serialize.JSON.MergeDataForReceiver(&mergeDataMap, existMapVal, data); nil != err {
return err
}
if s.res, err = sjson.Set(s.res, dataPath, mergeDataMap); nil != err {
return err
}
return nil
}
func (s *SjsonWrite) Result() string {
s.l.RLock()
defer s.l.RUnlock()
return s.res
}
func (s *SjsonWrite) Map() (map[string]any, error) {
var (
mapRes map[string]any
err error
)
if err = s.MapWithReceiver(&mapRes); nil != err {
return nil, err
}
return mapRes, nil
}
func (s *SjsonWrite) MapWithReceiver(receiver any) error {
return serialize.JSON.UnmarshalWithNumberForString(s.Result(), receiver)
}
func (s *SjsonWrite) Array() ([]any, error) {
var (
arrRes []any
err error
)
if err = s.ArrayWithReceiver(&arrRes); nil != err {
return nil, err
}
return arrRes, nil
}
func (s *SjsonWrite) ArrayWithReceiver(receiver any) error {
return serialize.JSON.UnmarshalWithNumberForString(s.Result(), receiver)
}

66
sjson_hack/set.go Normal file
View File

@ -0,0 +1,66 @@
// Package sjson_hack ...
//
// Description : sjson_hack ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-12-03 11:36
package sjson_hack
import (
"errors"
"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) {
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
View 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)
}