// Package json_tool ... // // Description : 将复杂数据结构转化为 JSONNode 树 // // Author : go_developer@163.com<白茶清欢> // // Date : 2021-03-14 10:40 下午 package json_tool import ( "encoding/json" "fmt" "github.com/tidwall/gjson" "strings" "github.com/pkg/errors" ) // MapDataRule 数据映射结果 // // Author : go_developer@163.com<白茶清欢> // // Date : 5:09 PM 2022/1/17 type MapDataRule struct { MapKey string DefaultValue string IsComplexType bool } // NewFilter 获取解析的实例 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:43 下午 2021/3/14 func NewFilter(data interface{}, rule map[string]MapDataRule) *Filter { return &Filter{ data: data, rule: rule, } } // Filter 解析json树 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:41 下午 2021/3/14 type Filter struct { data interface{} rule map[string]MapDataRule } // Result 数据过滤结果 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:44 下午 2021/3/14 func (f *Filter) Result() (*DynamicJSON, error) { if !f.isLegalData() { return nil, errors.New("非法的数据,无法转换成json") } result := NewDynamicJSON() byteData, _ := json.Marshal(f.data) source := string(byteData) for extraDataPath, newDataRule := range f.rule { // 为数组的处理 pathArr := strings.Split(extraDataPath, ".[].") val := gjson.Get(source, pathArr[0]) if len(pathArr) == 1 { f.SetValue(result, newDataRule.MapKey, val.Value(), false, 0) continue } // 支持list再抽取一层,处于性能考虑,这么限制,不做递归无限深度处理 // 还能继续抽取,就认为是 []map[string]interface{} keyList := strings.Split(pathArr[1], ".") for idx, item := range val.Array() { data := item.Map() for _, key := range keyList { if _, exist := data[key]; exist { result.SetValue(strings.ReplaceAll(newDataRule.MapKey, "[]", fmt.Sprintf("[%d]", idx)), data[key].String(), newDataRule.IsComplexType) } else { // 结果集中不存在对应key,设置默认值 result.SetValue(strings.ReplaceAll(newDataRule.MapKey, "[]", fmt.Sprintf("[%d]", idx)), newDataRule.DefaultValue, newDataRule.IsComplexType) } } } } return result, nil } // SetValue 设置值 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:14 下午 2021/9/10 func (f *Filter) SetValue(result *DynamicJSON, path string, val interface{}, isSetSlice bool, sliceIndex int) { if !isSetSlice { result.SetValue(path, val, false) return } } // isLegalData 判断是否能转换成json结构, 只有slice/map/struct/能转换成slice或map的[]byte是合法的 // // Author : go_developer@163.com<白茶清欢> // // Date : 10:46 下午 2021/3/14 func (f *Filter) isLegalData() bool { byteData, _ := json.Marshal(f.data) dataRes := gjson.Parse(string(byteData)) return dataRes.IsObject() || dataRes.IsArray() }