Merge pull request '升级json操作, 升级为面向接口实现' (#10) from feature/upgrade_get_set into master
Reviewed-on: #10
This commit is contained in:
commit
6c2c68c53e
36
abstract/json_read.go
Normal file
36
abstract/json_read.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// 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)
|
||||||
|
// 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)
|
||||||
|
}
|
24
abstract/json_write.go
Normal file
24
abstract/json_write.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// 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
|
||||||
|
// Result 最终结果以字符串形式返回
|
||||||
|
Result() string
|
||||||
|
// Map 最终结果以map返回
|
||||||
|
Map() (map[string]any, error)
|
||||||
|
// MapWithReceiver 外部指针接收返回值
|
||||||
|
MapWithReceiver(receiver any) error
|
||||||
|
// Array 最终结果以数组返回
|
||||||
|
Array() ([]any, error)
|
||||||
|
// ArrayWithReceiver 外部指针接收返回值
|
||||||
|
ArrayWithReceiver(receiver any) error
|
||||||
|
}
|
68
filter.go
68
filter.go
@ -8,19 +8,31 @@
|
|||||||
package filter
|
package filter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"git.zhangdeman.cn/zhangdeman/json_filter/abstract"
|
||||||
|
"git.zhangdeman.cn/zhangdeman/json_filter/implement"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack"
|
|
||||||
"git.zhangdeman.cn/zhangdeman/serialize"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"github.com/tidwall/sjson"
|
|
||||||
|
|
||||||
"errors"
|
"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 过滤器实例
|
// NewFilter 过滤器实例
|
||||||
//
|
//
|
||||||
// Author : go_developer@163.com<白茶清欢>
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
@ -29,7 +41,8 @@ import (
|
|||||||
func NewFilter(sourceData string, filterRuleList []MapRule) *filter {
|
func NewFilter(sourceData string, filterRuleList []MapRule) *filter {
|
||||||
return &filter{
|
return &filter{
|
||||||
sourceData: sourceData,
|
sourceData: sourceData,
|
||||||
formatResult: "{}",
|
jsonRaad: implement.NewGjsonRead(sourceData),
|
||||||
|
jsonWrite: implement.NewSjsonWrite(),
|
||||||
filterRuleList: filterRuleList,
|
filterRuleList: filterRuleList,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,8 +53,9 @@ func NewFilter(sourceData string, filterRuleList []MapRule) *filter {
|
|||||||
//
|
//
|
||||||
// Date : 11:58 2022/7/4
|
// Date : 11:58 2022/7/4
|
||||||
type filter struct {
|
type filter struct {
|
||||||
|
jsonRaad abstract.IJsonRead
|
||||||
|
jsonWrite abstract.IJsonWrite
|
||||||
sourceData string
|
sourceData string
|
||||||
formatResult string
|
|
||||||
filterRuleList []MapRule
|
filterRuleList []MapRule
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,33 +140,10 @@ func (f *filter) setResult(rule MapRule) error {
|
|||||||
err error
|
err error
|
||||||
formatVal any
|
formatVal any
|
||||||
)
|
)
|
||||||
|
if formatVal, err = f.jsonRaad.Value(rule.SourcePath, rule.DataType.String(), rule.DefaultValue); nil != err {
|
||||||
sourceResult := gjson.Get(f.sourceData, rule.SourcePath)
|
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 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 {
|
if err = f.jsonWrite.Set(rule.TargetPath, formatVal); nil != err {
|
||||||
// 获取的数据是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 err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -182,7 +173,7 @@ func (f *filter) getAllFinalData(res *[]string, resultList []gjson.Result, pathA
|
|||||||
//
|
//
|
||||||
// Date : 21:18 2022/12/31
|
// Date : 21:18 2022/12/31
|
||||||
func (f *filter) String() string {
|
func (f *filter) String() string {
|
||||||
return f.formatResult
|
return f.jsonWrite.Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Byte 获取格式化之后的字节数组
|
// Byte 获取格式化之后的字节数组
|
||||||
@ -199,9 +190,10 @@ func (f *filter) Byte() []byte {
|
|||||||
// Author : go_developer@163.com<白茶清欢>
|
// Author : go_developer@163.com<白茶清欢>
|
||||||
//
|
//
|
||||||
// Date : 21:20 2022/12/31
|
// Date : 21:20 2022/12/31
|
||||||
func (f *filter) Parse(receiver interface{}) error {
|
func (f *filter) Parse(receiver any) error {
|
||||||
if nil == receiver {
|
if nil == receiver {
|
||||||
return errors.New("receiver is nil")
|
return errors.New("receiver is nil")
|
||||||
}
|
}
|
||||||
return json.Unmarshal(f.Byte(), receiver)
|
return f.jsonWrite.MapWithReceiver(receiver)
|
||||||
|
// return json.Unmarshal(f.Byte(), receiver)
|
||||||
}
|
}
|
||||||
|
126
implement/gjson_read.go
Normal file
126
implement/gjson_read.go
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
return consts.DataTypeFloat64.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(g.gjsonResult.Get(dataPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gjsonRead) Uint(dataPath string) (uint64, error) {
|
||||||
|
return gjson_hack.Uint(g.gjsonResult.Get(dataPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gjsonRead) Float(dataPath string) (float64, error) {
|
||||||
|
return gjson_hack.Float64(g.gjsonResult.Get(dataPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
114
implement/sjson_write.go
Normal file
114
implement/sjson_write.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// 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) 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 {
|
||||||
|
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.res, 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.res, receiver)
|
||||||
|
}
|
@ -9,7 +9,6 @@ package sjson_hack
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack"
|
"git.zhangdeman.cn/zhangdeman/json_filter/gjson_hack"
|
||||||
"git.zhangdeman.cn/zhangdeman/wrapper"
|
"git.zhangdeman.cn/zhangdeman/wrapper"
|
||||||
"github.com/tidwall/sjson"
|
"github.com/tidwall/sjson"
|
||||||
@ -27,7 +26,6 @@ var (
|
|||||||
//
|
//
|
||||||
// Date : 11:36 2024/12/3
|
// Date : 11:36 2024/12/3
|
||||||
func Set(jsonRes string, path string, value any) (string, error) {
|
func Set(jsonRes string, path string, value any) (string, error) {
|
||||||
fmt.Println(jsonRes, value)
|
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
res string = jsonRes
|
res string = jsonRes
|
||||||
|
Loading…
x
Reference in New Issue
Block a user