// Package tree ... // // Description : tree ... // // Author : go_developer@163.com<白茶清欢> // // Date : 2023-03-28 18:42 package tree import ( "fmt" "strings" "github.com/pkg/errors" ) // New 生成一棵JSON树 // // Author : go_developer@163.com<白茶清欢> // // Date : 18:42 2023/3/28 func New(jsonData string) (*Generate, error) { jsonData = strings.TrimSpace(jsonData) g := &Generate{ jsonData: jsonData, jsonDataByte: []byte(jsonData), } g.root = NewVirtualNode() g.currentNode = g.root err := g.init() return g, err } // Generate ... // // Author : go_developer@163.com<白茶清欢> // // Date : 22:46 2023/3/28 type Generate struct { root *Node // 根节点 currentNode *Node // 当前节点 currentParentNode *Node // 当前节点的父节点 jsonData string jsonDataByte []byte } // init 初始化 // // Author : go_developer@163.com<白茶清欢> // // Date : 21:23 2023/3/29 func (g *Generate) init() error { startIndex := 0 var ( jsonKey string err error valueType string ) // 获取类型 if valueType, startIndex, err = g.getValueType(startIndex); nil != err { return err } g.root.ValueType = valueType for { if startIndex >= len(g.jsonDataByte) { break } // 获取字段 if jsonKey, startIndex, err = g.getKey(startIndex); nil != err { return err } // 获取类型 if valueType, startIndex, err = g.getValueType(startIndex); nil != err { return err } fmt.Println(jsonKey, valueType, startIndex) } return nil } // getKey 获取jsonKey TODO : 转义符识别 // // Author : zhangdeman001@ke.com<张德满> // // Date : 11:36 2023/3/29 func (g *Generate) getKey(startIndex int) (string, int, error) { keyCharList := []string{} hasStart := false for startIndex < len(g.jsonDataByte) { charStr := string(g.jsonDataByte[startIndex]) if charStr == KeywordSpace { // 跳过空格 startIndex++ continue } if charStr == KeywordDoubleQuote && !hasStart { // 第一次遇见双引号 startIndex++ hasStart = true continue } if charStr == KeywordDoubleQuote && hasStart { // 第二次遇见双引号,key探寻结束 startIndex++ break } keyCharList = append(keyCharList, charStr) startIndex++ } jsonKey := strings.Join(keyCharList, "") return jsonKey, startIndex, nil } // getValueType 获取数据类型 // // Author : go_developer@163.com<白茶清欢> // // Date : 14:37 2023/3/29 func (g *Generate) getValueType(startIndex int) (string, int, error) { if startIndex == 0 { // 初始对象特殊处理 if string(g.jsonDataByte[0]) == KeywordArrayStart { return ValueTypeArray, 1, nil } // 初始对象特殊处理 if string(g.jsonDataByte[0]) == KeywordObjectStart { return ValueTypeMap, 1, nil } return "", 0, errors.New("root data parse : value is invalid") } // 指针向后, 探寻到冒号之后第一个非空格字符串 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 !hasFindColon { return "", startIndex, errors.New("check json value type : value is invalid") } keyValType := "" // 冒号后面探寻值的类型 for startIndex < len(g.jsonDataByte) { charStr := string(g.jsonDataByte[startIndex]) if charStr == KeywordSpace { // 跳过空格 startIndex++ continue } // 非空 switch charStr { case KeywordMinus: fallthrough case KeywordOne: fallthrough case KeywordTwo: fallthrough case KeywordThree: fallthrough case KeywordFour: fallthrough case KeywordFive: fallthrough case KeywordSix: fallthrough case KeywordSeven: fallthrough case KeywordEight: fallthrough case KeywordNine: keyValType = ValueTypeNumber case KeywordDoubleQuote: keyValType = ValueTypeString case KeywordArrayStart: keyValType = ValueTypeArray case KeywordObjectStart: keyValType = ValueTypeMap default: return "", startIndex, errors.New("validate json value type : value type is invalid") } break } return keyValType, startIndex, nil } // isObject 整体是否为对象 // // Author : go_developer@163.com<白茶清欢> // // Date : 22:51 2023/3/28 func (g *Generate) isObject() bool { return strings.HasPrefix(g.jsonData, KeywordObjectStart) } // isArray 整体是否为数组 // // Author : go_developer@163.com<白茶清欢> // // Date : 22:51 2023/3/28 func (g *Generate) isArray() bool { return strings.HasPrefix(g.jsonData, KeywordArrayStart) }