json_filter/tree/generate.go
2024-09-23 15:59:09 +08:00

320 lines
7.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package tree ...
//
// Description : tree ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-03-28 18:42
package tree
import (
"fmt"
"git.zhangdeman.cn/zhangdeman/wrapper"
"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
g.currentParentNode = 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
g.currentNode.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)
// 创建节点, 并挂在到树上
var newNode *Node
if wrapper.ArrayType([]string{ValueTypeArray, ValueTypeMap}).Has(g.currentNode.ValueType) >= 0 {
newNode = NewNode(jsonKey, jsonValue, valueType, g.currentNode)
g.currentParentNode = g.currentNode
g.currentParentNode.SonNodeList = append(g.currentParentNode.SonNodeList, newNode)
} else {
newNode = NewNode(jsonKey, jsonValue, valueType, g.currentParentNode)
}
g.currentNode = newNode
}
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 := make([]string, 0)
hasStart := false
for startIndex < len(g.jsonDataByte) {
charStr := string(g.jsonDataByte[startIndex])
if charStr == KeywordSpace && !hasStart {
// 跳过空格
startIndex++
continue
}
if charStr == KeywordDoubleQuote {
if !hasStart {
// 第一次遇见双引号
startIndex++
hasStart = true
continue
} else {
// 第二次遇见双引号key探寻结束
startIndex++
break
}
}
if !hasStart {
if wrapper.ArrayType([]string{
KeywordDoubleQuote,
KeywordObjectStart,
KeywordArrayStart,
KeywordComma,
}).Has(charStr) >= 0 {
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 charStr == KeywordSpace {
// 跳过空格
startIndex++
continue
} else {
// 非空格
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 && !isStart {
startIndex++
continue
}
if !isStart {
if wrapper.ArrayType([]string{KeywordArrayEnd, KeywordObjectEnd, KeywordComma}).Has(str) >= 0 {
startIndex++
continue
}
}
if isStart {
if wrapper.ArrayType([]string{KeywordDoubleQuote, KeywordArrayEnd, KeywordObjectEnd, KeywordComma}).Has(str) >= 0 {
// 值的拼接已结束
startIndex++
break
}
}
if str == KeywordDoubleQuote {
if isStart {
startIndex++
break
} else {
startIndex++
isStart = true
continue
}
}
isStart = true
if str == KeywordEscapeSymbol {
// 转义符
startIndex++
if startIndex >= len(g.jsonDataByte) {
// 转义符后面没东西了
return "", startIndex, errors.New("escape symbol without any data")
}
str = string(g.jsonDataByte[startIndex])
}
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)
}