优化自动生成json #3
							
								
								
									
										113
									
								
								filter.go
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								filter.go
									
									
									
									
									
								
							| @ -10,14 +10,13 @@ package filter | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"git.zhangdeman.cn/zhangdeman/wrapper" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/tidwall/gjson" | ||||
| 	"github.com/tidwall/sjson" | ||||
|  | ||||
| 	"errors" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/util" | ||||
| ) | ||||
|  | ||||
| // NewFilter 过滤器实例 | ||||
| @ -64,17 +63,7 @@ func (f *filter) Deal() error { | ||||
| 			continue | ||||
| 		} | ||||
| 		sourceResult := gjson.Get(f.sourceData, rule.SourcePath) | ||||
| 		var ( | ||||
| 			sourceVal string | ||||
| 		) | ||||
|  | ||||
| 		if !sourceResult.Exists() { | ||||
| 			// 不存在, 使用默认值 | ||||
| 			sourceVal = rule.DefaultValue | ||||
| 		} else { | ||||
| 			sourceVal = sourceResult.String() | ||||
| 		} | ||||
| 		if formatVal, err = f.getValue(rule.DataType, sourceVal); nil != err { | ||||
| 		if formatVal, err = f.getValue(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 f.formatResult, err = sjson.Set(f.formatResult, rule.MapPath, formatVal); nil != err { | ||||
| @ -183,56 +172,60 @@ func (f *filter) Parse(receiver interface{}) error { | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 12:25 2022/7/4 | ||||
| func (f *filter) getValue(dataType string, defaultValue string) (interface{}, error) { | ||||
| func (f *filter) getValue(dataType string, sourceValue gjson.Result, defaultValue string) (interface{}, error) { | ||||
| 	sourceValueStr := defaultValue | ||||
| 	if sourceValue.Exists() { | ||||
| 		str := sourceValue.String() | ||||
| 		if len(str) > 0 { | ||||
| 			sourceValueStr = str | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	strVal := wrapper.String(sourceValueStr) | ||||
|  | ||||
| 	switch dataType { | ||||
| 	case "int8": | ||||
| 	case wrapper.DataTypeInt8: | ||||
| 		return strVal.ToInt8() | ||||
| 	case wrapper.DataTypeInt16: | ||||
| 		return strVal.ToInt16() | ||||
| 	case wrapper.DataTypeInt32: | ||||
| 		return strVal.ToInt32() | ||||
| 	case wrapper.DataTypeInt64: | ||||
| 		return strVal.ToInt64() | ||||
| 	case wrapper.DataTypeInt: | ||||
| 		return strVal.ToInt() | ||||
| 	case wrapper.DataTypeUint8: | ||||
| 		return strVal.ToUint8() | ||||
| 	case wrapper.DataTypeUint16: | ||||
| 		return strVal.ToUint16() | ||||
| 	case wrapper.DataTypeUint32: | ||||
| 		return strVal.ToUint32() | ||||
| 	case wrapper.DataTypeUint64: | ||||
| 		return strVal.ToUint64() | ||||
| 	case wrapper.DataTypeUint: | ||||
| 		return strVal.ToUint() | ||||
| 	case wrapper.DataTypeBool: | ||||
| 		return strVal.ToBool() | ||||
| 	case wrapper.DataTypeFloat32: | ||||
| 		return strVal.ToFloat64() | ||||
| 	case wrapper.DataTypeFloat64: | ||||
| 		fallthrough | ||||
| 	case "int16": | ||||
| 	case wrapper.DataTypeFloat: | ||||
| 		fallthrough | ||||
| 	case "int32": | ||||
| 		fallthrough | ||||
| 	case "int64": | ||||
| 		fallthrough | ||||
| 	case "int": | ||||
| 		var ( | ||||
| 			err error | ||||
| 			val int64 | ||||
| 		) | ||||
| 		err = util.ConvertAssign(&val, defaultValue) | ||||
| 		return val, err | ||||
| 	case "uint8": | ||||
| 		fallthrough | ||||
| 	case "uint16": | ||||
| 		fallthrough | ||||
| 	case "uint32": | ||||
| 		fallthrough | ||||
| 	case "uint64": | ||||
| 		fallthrough | ||||
| 	case "uint": | ||||
| 		var ( | ||||
| 			err error | ||||
| 			val uint64 | ||||
| 		) | ||||
| 		err = util.ConvertAssign(&val, defaultValue) | ||||
| 		return val, err | ||||
| 	case "bool": | ||||
| 		var ( | ||||
| 			err error | ||||
| 			val bool | ||||
| 		) | ||||
| 		err = util.ConvertAssign(&val, defaultValue) | ||||
| 		return val, err | ||||
| 	case "float32": | ||||
| 		fallthrough | ||||
| 	case "float64": | ||||
| 		var ( | ||||
| 			err error | ||||
| 			val float64 | ||||
| 		) | ||||
| 		err = util.ConvertAssign(&val, defaultValue) | ||||
| 		return val, err | ||||
| 	case "string": | ||||
| 		return defaultValue, nil | ||||
| 	case wrapper.DataTypeDouble: | ||||
| 		return strVal.ToFloat64() | ||||
| 	case wrapper.DataTypeNumber: | ||||
| 		return strVal.ToNumber() | ||||
| 	case wrapper.DataTypeString: | ||||
| 		return sourceValueStr, nil | ||||
| 	case wrapper.DataTypeAny: | ||||
| 		return sourceValue.Value(), nil | ||||
| 	case wrapper.DataTypeAnySlice: | ||||
| 		// 任意类型的list | ||||
| 		return strVal.ToAnySlice() | ||||
| 	case wrapper.DataTypeObject: | ||||
| 		// object | ||||
| 		return strVal.ToObject() | ||||
| 	default: | ||||
| 		return nil, errors.New(dataType + " is not support!") | ||||
| 	} | ||||
|  | ||||
							
								
								
									
										7
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								go.mod
									
									
									
									
									
								
							| @ -1,10 +1,10 @@ | ||||
| module git.zhangdeman.cn/zhangdeman/json_filter | ||||
|  | ||||
| go 1.17 | ||||
| go 1.18 | ||||
|  | ||||
| require ( | ||||
| 	git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20220627070212-c590a0a1c216 | ||||
| 	git.zhangdeman.cn/zhangdeman/util v0.0.0-20230211164227-256094968151 | ||||
| 	git.zhangdeman.cn/zhangdeman/util v0.0.0-20230505025924-96532aff0019 | ||||
| 	github.com/Jeffail/gabs v1.4.0 | ||||
| 	github.com/pkg/errors v0.9.1 | ||||
| 	github.com/smartystreets/goconvey v1.7.2 | ||||
| @ -13,12 +13,15 @@ require ( | ||||
| ) | ||||
|  | ||||
| require ( | ||||
| 	git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230505080742-fa2f27724d76 // indirect | ||||
| 	github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect | ||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||
| 	github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect | ||||
| 	github.com/go-ini/ini v1.67.0 // indirect | ||||
| 	github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect | ||||
| 	github.com/jtolds/gls v4.20.0+incompatible // indirect | ||||
| 	github.com/mitchellh/go-homedir v1.1.0 // indirect | ||||
| 	github.com/mssola/user_agent v0.6.0 // indirect | ||||
| 	github.com/pmezard/go-difflib v1.0.0 // indirect | ||||
| 	github.com/smartystreets/assertions v1.2.0 // indirect | ||||
| 	github.com/spaolacci/murmur3 v1.1.0 // indirect | ||||
|  | ||||
							
								
								
									
										16
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								go.sum
									
									
									
									
									
								
							| @ -3,6 +3,18 @@ git.zhangdeman.cn/zhangdeman/easylock v0.0.0-20220627070212-c590a0a1c216/go.mod | ||||
| git.zhangdeman.cn/zhangdeman/util v0.0.0-20220626081130-cbac0b676fb8/go.mod h1:G2/OKMbEn89d+YUXQtv9Nlh0LGg14pOqDnbOgBTTRXY= | ||||
| git.zhangdeman.cn/zhangdeman/util v0.0.0-20230211164227-256094968151 h1:j537bRLQL1FlkdXTIaT9Ecjx5eogkPsGiTOWIEFQlc8= | ||||
| git.zhangdeman.cn/zhangdeman/util v0.0.0-20230211164227-256094968151/go.mod h1:SyRTkOz6gxUVn3S/Qtkf+rhKV0I1ym8lwsT8YjggYFs= | ||||
| git.zhangdeman.cn/zhangdeman/util v0.0.0-20230330065032-faba0a5a9ea1 h1:u2FdNfcGvRmlKpuPBk2qvYenkZjinHY2PLu5Wmhka8A= | ||||
| git.zhangdeman.cn/zhangdeman/util v0.0.0-20230330065032-faba0a5a9ea1/go.mod h1:SyRTkOz6gxUVn3S/Qtkf+rhKV0I1ym8lwsT8YjggYFs= | ||||
| git.zhangdeman.cn/zhangdeman/util v0.0.0-20230330082619-662152cb682d h1:kMQZmkYBceHM3O7wiCelSADjTyOF3EBxXTX8fgZA+6c= | ||||
| git.zhangdeman.cn/zhangdeman/util v0.0.0-20230330082619-662152cb682d/go.mod h1:qeVsrMae8ljqzcsmI+lWPU/4Rdjb9cOt4oaDUNEf1Ck= | ||||
| git.zhangdeman.cn/zhangdeman/util v0.0.0-20230505025924-96532aff0019 h1:eJ/9rEj2iI8P9I1DfCmMUvsV+n2EiAWCXnI9yVVDHO0= | ||||
| git.zhangdeman.cn/zhangdeman/util v0.0.0-20230505025924-96532aff0019/go.mod h1:z2bP5LIwRVpWSQV0/a3WIFaoarJUP8kA/0Clv0bP+8I= | ||||
| git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230505064614-5e785171ed67 h1:DH9K3fNddpFxRGLkcLP5MHsAQVinpWpmGzbVBf8yrKM= | ||||
| git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230505064614-5e785171ed67/go.mod h1:2jc48WuVoHxZjkvlBewzp+ey8khP1K4OOcibVD1yL2k= | ||||
| git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230505070245-b182b21e039b h1:ZwAA10/+v3FFAq5/EzjXdXDodmKppXb5gBkCcgaYVBo= | ||||
| git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230505070245-b182b21e039b/go.mod h1:2jc48WuVoHxZjkvlBewzp+ey8khP1K4OOcibVD1yL2k= | ||||
| git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230505080742-fa2f27724d76 h1:IEixZNZY3/nqb5v9PzzgSeXLPp0U7wRaxrM+ZaSh+j0= | ||||
| git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20230505080742-fa2f27724d76/go.mod h1:2jc48WuVoHxZjkvlBewzp+ey8khP1K4OOcibVD1yL2k= | ||||
| github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo= | ||||
| github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= | ||||
| github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ= | ||||
| @ -18,6 +30,10 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGa | ||||
| github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | ||||
| github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= | ||||
| github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | ||||
| github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= | ||||
| github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= | ||||
| github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= | ||||
| github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= | ||||
| github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||||
| github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
|  | ||||
							
								
								
									
										3
									
								
								tree/REDME.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tree/REDME.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| # 说明 | ||||
|  | ||||
| 基于JSON数据生成数据树 | ||||
							
								
								
									
										73
									
								
								tree/consts.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								tree/consts.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | ||||
| // Package tree ... | ||||
| // | ||||
| // Description : tree ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2023-03-28 18:32 | ||||
| package tree | ||||
|  | ||||
| const ( | ||||
| 	// KeywordObjectStart 对象开始标识 | ||||
| 	KeywordObjectStart = "{" | ||||
| 	// KeywordObjectEnd 对象结束标识 | ||||
| 	KeywordObjectEnd = "}" | ||||
| 	// KeywordArrayStart 数组开始标识 | ||||
| 	KeywordArrayStart = "[" | ||||
| 	// KeywordArrayEnd 数组结束标识 | ||||
| 	KeywordArrayEnd = "]" | ||||
| 	// KeywordColon 冒号 | ||||
| 	KeywordColon = ":" | ||||
| 	// KeywordComma 逗号 | ||||
| 	KeywordComma = "," | ||||
| 	// KeywordDot . | ||||
| 	KeywordDot = "." | ||||
| 	// KeywordDoubleQuote 双引号 | ||||
| 	KeywordDoubleQuote = `"` | ||||
| 	// KeywordEscapeSymbol 转义符号 | ||||
| 	KeywordEscapeSymbol = `\` | ||||
| 	// KeywordSpace 空格 | ||||
| 	KeywordSpace = " " | ||||
| 	// KeywordMinus 负号 | ||||
| 	KeywordMinus = "-" | ||||
| 	// KeywordTrueStart true的起始值 | ||||
| 	KeywordTrueStart = "t" | ||||
| 	// KeywordFalseStart false的起始值 | ||||
| 	KeywordFalseStart = "f" | ||||
| 	KeywordZero       = "0" | ||||
| 	KeywordOne        = "1" | ||||
| 	KeywordTwo        = "2" | ||||
| 	KeywordThree      = "3" | ||||
| 	KeywordFour       = "4" | ||||
| 	KeywordFive       = "5" | ||||
| 	KeywordSix        = "6" | ||||
| 	KeywordSeven      = "7" | ||||
| 	KeywordEight      = "8" | ||||
| 	KeywordNine       = "9" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// ValueTypeString 字符串类型 | ||||
| 	ValueTypeString = "string" | ||||
| 	// ValueTypeBool bool类型 | ||||
| 	ValueTypeBool = "bool" | ||||
| 	// ValueTypeInteger int类型 | ||||
| 	ValueTypeInteger = "int64" | ||||
| 	// ValueTypeFloat float类型 | ||||
| 	ValueTypeFloat = "float64" | ||||
| 	// ValueTypeNumber 数字 | ||||
| 	ValueTypeNumber = "number" | ||||
| 	// ValueTypeMap map数据 | ||||
| 	ValueTypeMap = "map" | ||||
| 	// ValueTypeArray 数组 | ||||
| 	ValueTypeArray = "array" | ||||
| ) | ||||
|  | ||||
| // isBaseDataType 是否为基础数据类型 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 23:16 2023/3/28 | ||||
| func isBaseDataType(valueType string) bool { | ||||
| 	return valueType != ValueTypeArray && valueType != ValueTypeMap | ||||
| } | ||||
							
								
								
									
										321
									
								
								tree/generate.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								tree/generate.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,321 @@ | ||||
| // Package tree ... | ||||
| // | ||||
| // Description : tree ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2023-03-28 18:42 | ||||
| package tree | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"git.zhangdeman.cn/zhangdeman/util" | ||||
| 	"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 util.Array.In(g.currentNode.ValueType, []string{ValueTypeArray, ValueTypeMap}) >= 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 && !hasStart { | ||||
| 			// 第一次遇见双引号 | ||||
| 			startIndex++ | ||||
| 			hasStart = true | ||||
| 			continue | ||||
| 		} | ||||
| 		if charStr == KeywordDoubleQuote && hasStart { | ||||
| 			// 第二次遇见双引号,key探寻结束 | ||||
| 			startIndex++ | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		if !hasStart { | ||||
| 			if util.Array.In(charStr, []string{ | ||||
| 				KeywordDoubleQuote, | ||||
| 				KeywordObjectStart, | ||||
| 				KeywordArrayStart, | ||||
| 				KeywordComma, | ||||
| 			}) >= 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 !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 && !isStart { | ||||
| 			startIndex++ | ||||
| 			continue | ||||
| 		} | ||||
| 		if !isStart { | ||||
| 			if util.Array.In(str, []string{KeywordArrayEnd, KeywordObjectEnd, KeywordComma}) >= 0 { | ||||
| 				startIndex++ | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 		if isStart { | ||||
| 			if util.Array.In(str, []string{KeywordDoubleQuote, KeywordArrayEnd, KeywordObjectEnd, KeywordComma}) >= 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) | ||||
| } | ||||
							
								
								
									
										23
									
								
								tree/generate_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tree/generate_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| // Package tree ... | ||||
| // | ||||
| // Description : tree ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2023-03-29 21:32 | ||||
| package tree | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestNew(t *testing.T) { | ||||
| 	jsonData := `{"name": "zhang", "age":17}` | ||||
| 	g, err := New(jsonData) | ||||
| 	if nil != err { | ||||
| 		fmt.Println(err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	fmt.Println(g) | ||||
| } | ||||
							
								
								
									
										108
									
								
								tree/node.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								tree/node.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | ||||
| // Package tree ... | ||||
| // | ||||
| // Description : tree ... | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 2023-03-28 18:12 | ||||
| package tree | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"git.zhangdeman.cn/zhangdeman/util" | ||||
| ) | ||||
|  | ||||
| // Node 节点的数据结构 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 18:12 2023/3/28 | ||||
| type Node struct { | ||||
| 	IsVirtual       bool        // 是否虚拟节点, 主要应对输入的原始数据为list这一场景 | ||||
| 	Value           interface{} // 节点的值 | ||||
| 	ValueType       string      // 数据类型 string / int64 / float64 / map / list / nil | ||||
| 	Key             string      // 节点的key名称(输入的原始名称) | ||||
| 	Show            bool        // 节点是否可见 | ||||
| 	ShowKey         string      // 重新序列化后, 对外输出的Key | ||||
| 	AllowEdit       bool        // 当前key是否允许编辑 | ||||
| 	AllowChangeType bool        // 在允许编辑的情况下, 是否允许修改数据类型 | ||||
| 	DefaultValue    interface{} // 输入为value为nil时候的默认值 | ||||
| 	ParentNode      *Node       // 父节点 | ||||
| 	PreBrotherNode  *Node       // 前一个兄弟节点 | ||||
| 	LastBrotherNode *Node       // 下一个兄弟节点 | ||||
| 	SonNodeList     []*Node     // 子节点列表 | ||||
| 	ObjectStack     []string    // 对象信息堆栈, 利用栈的括号匹配, 判断某一个对象是否扫面完成 | ||||
| } | ||||
|  | ||||
| // NewNode 创建新节点 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 23:02 2023/3/28 | ||||
| func NewNode(key string, value string, valueType string, parentNode *Node) *Node { | ||||
| 	n := &Node{ | ||||
| 		IsVirtual:       false, | ||||
| 		Value:           value, | ||||
| 		ValueType:       valueType, | ||||
| 		Key:             key, | ||||
| 		Show:            false, | ||||
| 		ShowKey:         "", | ||||
| 		AllowEdit:       false, | ||||
| 		AllowChangeType: false, | ||||
| 		DefaultValue:    nil, | ||||
| 		ParentNode:      parentNode, | ||||
| 		PreBrotherNode:  nil, | ||||
| 		LastBrotherNode: nil, | ||||
| 		SonNodeList:     nil, | ||||
| 		ObjectStack:     make([]string, 0), | ||||
| 	} | ||||
|  | ||||
| 	switch valueType { | ||||
| 	case ValueTypeString: | ||||
| 		n.Value = value | ||||
| 	case ValueTypeInteger: | ||||
| 		var v int64 | ||||
| 		_ = util.ConvertAssign(&v, value) | ||||
| 		n.Value = v | ||||
| 	case ValueTypeFloat: | ||||
| 		var v float64 | ||||
| 		_ = util.ConvertAssign(&v, value) | ||||
| 		n.Value = v | ||||
| 	case ValueTypeBool: | ||||
| 		n.Value = strings.ToLower(value) == "true" | ||||
| 	case ValueTypeMap: | ||||
| 		n.Value = map[string]interface{}{} | ||||
| 		n.SonNodeList = make([]*Node, 0) | ||||
| 	case ValueTypeArray: | ||||
| 		n.Value = []interface{}{} | ||||
| 		n.SonNodeList = make([]*Node, 0) | ||||
| 	} | ||||
|  | ||||
| 	// 处理 preBrother 和 lastBrother | ||||
| 	if parentNode.ValueType == ValueTypeMap || parentNode.ValueType == ValueTypeArray { | ||||
| 		// map 和 array 才有所谓的兄弟节点 | ||||
| 		if len(parentNode.SonNodeList) > 0 { | ||||
| 			// 设置新节点的 pre 节点 | ||||
| 			n.PreBrotherNode = parentNode.SonNodeList[len(parentNode.SonNodeList)-1] | ||||
| 			// 设置当前最后一个节点的 last 节点 | ||||
| 			parentNode.SonNodeList[len(parentNode.SonNodeList)-1].LastBrotherNode = n | ||||
| 		} | ||||
| 		// 新节点追加到子节点末尾 | ||||
| 		parentNode.SonNodeList = append(parentNode.SonNodeList, n) | ||||
| 	} | ||||
| 	return n | ||||
| } | ||||
|  | ||||
| // NewVirtualNode 创建一个新的虚拟节点 | ||||
| // | ||||
| // Author : go_developer@163.com<白茶清欢> | ||||
| // | ||||
| // Date : 23:08 2023/3/28 | ||||
| func NewVirtualNode() *Node { | ||||
| 	return &Node{ | ||||
| 		IsVirtual:   true, | ||||
| 		SonNodeList: make([]*Node, 0), | ||||
| 		ObjectStack: make([]string, 0), | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user