// 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 jsonValue 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 } // 获取值 if jsonValue, startIndex, err = g.getValue(startIndex); nil != err { return err } fmt.Println(jsonKey, valueType, jsonValue, 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 } if !hasStart { if charStr == KeywordDoubleQuote || charStr == KeywordObjectStart || charStr == KeywordArrayStart || charStr == KeywordComma { startIndex++ continue } return "", startIndex, errors.New("parse key : format is invalid") } if charStr == KeywordEscapeSymbol { // 转义符 startIndex++ if startIndex >= len(g.jsonDataByte) { // 转义符后面没东西了 return "", startIndex, errors.New("escape symbol without any data") } charStr = string(g.jsonDataByte[startIndex]) } 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 } // getValue 获取JSON值 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:09 2023/3/30 func (g *Generate) getValue(startIndex int) (string, int, error) { valArr := make([]string, 0) isStart := false for startIndex < len(g.jsonDataByte) { str := string(g.jsonDataByte[startIndex]) if str == KeywordSpace { startIndex++ continue } if !isStart { if str == KeywordArrayEnd || str == KeywordObjectEnd || str == KeywordComma { startIndex++ continue } } if isStart { if str == KeywordDoubleQuote || str == KeywordArrayEnd || str == KeywordObjectEnd || str == KeywordComma { // 值的拼接已结束 startIndex++ break } } if str == KeywordDoubleQuote { if isStart { startIndex++ break } else { startIndex++ continue } } isStart = true valArr = append(valArr, str) startIndex++ } return strings.Join(valArr, ""), 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) }