2022-07-04 18:00:22 +08:00
|
|
|
// Package filter ...
|
|
|
|
//
|
|
|
|
// Description : JSON 词法分析
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 2022-07-04 17:52
|
|
|
|
package filter
|
2022-07-04 18:08:10 +08:00
|
|
|
|
2022-07-04 18:19:04 +08:00
|
|
|
import (
|
2022-07-04 18:39:29 +08:00
|
|
|
"git.zhangdeman.cn/zhangdeman/util"
|
2022-07-04 18:19:04 +08:00
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
2022-07-04 20:59:57 +08:00
|
|
|
// NewLexical 获取实例
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 20:52 2022/7/4
|
|
|
|
func NewLexical(jsonData string) *lexical {
|
2022-07-04 23:17:02 +08:00
|
|
|
return &lexical{
|
|
|
|
jsonData: jsonData,
|
|
|
|
lexicalResult: make([]*lexicalNode, 0),
|
|
|
|
}
|
2022-07-04 20:59:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// lexical 词法解析
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 20:42 2022/7/4
|
|
|
|
type lexical struct {
|
|
|
|
jsonData string
|
|
|
|
keyLeftRightTokenCnt int
|
2022-07-04 23:17:02 +08:00
|
|
|
lexicalResult []*lexicalNode
|
2022-07-04 20:59:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parse 解析词法
|
2022-07-04 18:19:04 +08:00
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 18:11 2022/7/4
|
2022-07-04 23:28:12 +08:00
|
|
|
func (l *lexical) Parse(jsonData string) ([]*lexicalNode, error) {
|
2022-07-04 19:03:15 +08:00
|
|
|
// mt.Println(jsonData)
|
2022-07-04 18:19:04 +08:00
|
|
|
if len(jsonData) < 2 {
|
|
|
|
return nil, errors.New("input data is not json")
|
|
|
|
}
|
2022-07-04 18:35:32 +08:00
|
|
|
tmpStr := ""
|
2022-07-04 18:19:04 +08:00
|
|
|
for _, itemChar := range jsonData {
|
2022-07-04 18:35:32 +08:00
|
|
|
currentChar := string(itemChar)
|
2022-07-04 23:17:02 +08:00
|
|
|
if l.inputCharIsToken(currentChar, tmpStr) {
|
2022-07-04 20:59:57 +08:00
|
|
|
if currentChar == keyLeftRightToken {
|
|
|
|
// 双引号计数
|
|
|
|
l.keyLeftRightTokenCnt++
|
|
|
|
}
|
2022-07-04 18:35:32 +08:00
|
|
|
// 是关键词
|
|
|
|
if len(tmpStr) > 0 {
|
2022-07-04 23:17:02 +08:00
|
|
|
l.lexicalResult = append(l.lexicalResult, &lexicalNode{
|
2022-07-04 18:35:32 +08:00
|
|
|
Val: tmpStr,
|
|
|
|
IsToken: false,
|
|
|
|
})
|
|
|
|
}
|
2022-07-04 23:17:02 +08:00
|
|
|
l.lexicalResult = append(l.lexicalResult, &lexicalNode{
|
2022-07-04 18:35:32 +08:00
|
|
|
Val: currentChar,
|
|
|
|
IsToken: true,
|
|
|
|
})
|
2022-07-04 18:47:50 +08:00
|
|
|
tmpStr = ""
|
2022-07-04 18:35:32 +08:00
|
|
|
} else {
|
|
|
|
// 不是关键词, 继续向后走
|
2022-07-05 11:18:53 +08:00
|
|
|
if currentChar == " " && l.keyLeftRightTokenCnt%2 == 0 {
|
|
|
|
// 当前字符是空格, 只有在 "" 之间方才有效 , 关键字之间的空格, 忽略即可
|
|
|
|
continue
|
2022-07-04 23:17:02 +08:00
|
|
|
}
|
2022-07-04 18:35:32 +08:00
|
|
|
tmpStr = tmpStr + currentChar
|
2022-07-05 11:18:53 +08:00
|
|
|
if (tmpStr == "\n" || tmpStr == "\t") && l.keyLeftRightTokenCnt%2 == 0 {
|
|
|
|
// 不在 "" 之间的 \n \t 无意义, 过滤掉
|
|
|
|
tmpStr = ""
|
|
|
|
}
|
2022-07-04 18:35:32 +08:00
|
|
|
}
|
2022-07-04 18:19:04 +08:00
|
|
|
}
|
2022-07-04 23:30:50 +08:00
|
|
|
if len(tmpStr) > 0 {
|
|
|
|
l.lexicalResult = append(l.lexicalResult, &lexicalNode{
|
|
|
|
Val: tmpStr,
|
|
|
|
IsToken: false,
|
|
|
|
})
|
|
|
|
tmpStr = ""
|
|
|
|
}
|
2022-07-05 11:18:53 +08:00
|
|
|
|
2022-07-04 23:28:12 +08:00
|
|
|
return l.lexicalResult, nil
|
2022-07-04 18:19:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// inputCharIsToken 输入字符是否为关键字
|
|
|
|
//
|
|
|
|
// Author : go_developer@163.com<白茶清欢>
|
|
|
|
//
|
|
|
|
// Date : 18:15 2022/7/4
|
2022-07-04 23:17:02 +08:00
|
|
|
func (l *lexical) inputCharIsToken(inputChar string, tmpStr string) bool {
|
|
|
|
if len(tmpStr) == 0 && inputChar == keyLeftRightToken {
|
|
|
|
// 双引号关键字
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
tmpStrByte := []byte(tmpStr)
|
|
|
|
if len(tmpStrByte) > 0 {
|
|
|
|
// 字符串拼接过程中, 只有 " 可能是关键字
|
|
|
|
// 判断转义符个数
|
|
|
|
escapeCharacterTokenCnt := 0
|
|
|
|
for i := len(tmpStrByte) - 1; i >= 0; i-- {
|
|
|
|
if string(tmpStrByte[i]) == escapeCharacterToken {
|
|
|
|
// 前一个是转义符
|
|
|
|
escapeCharacterTokenCnt++
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// 非连续的转义符不计数
|
|
|
|
break
|
|
|
|
}
|
|
|
|
// 0 个 或者 偶数个转义符, " 是关键字
|
2022-07-05 11:18:53 +08:00
|
|
|
if inputChar == keyLeftRightToken && escapeCharacterTokenCnt%2 == 0 {
|
2022-07-04 18:19:04 +08:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
2022-07-04 23:17:02 +08:00
|
|
|
|
|
|
|
var preNode *lexicalNode
|
|
|
|
if len(l.lexicalResult) > 0 {
|
|
|
|
preNode = l.lexicalResult[len(l.lexicalResult)-1]
|
|
|
|
}
|
|
|
|
|
|
|
|
if inputChar == colonToken && nil != preNode && preNode.Val == keyLeftRightToken && l.keyLeftRightTokenCnt > 0 && l.keyLeftRightTokenCnt%2 == 0 {
|
|
|
|
// : 必须出现在偶数 " 之后才是关键字
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpStrType := l.getTpmStrType(tmpStr)
|
|
|
|
// , 是关键字的场景
|
|
|
|
// {"name":"zhangsan", "age":"18"}
|
|
|
|
// [{"name":"zhangsan", "age":"18"}, {"name":"zhangsan", "age":"18"}]
|
|
|
|
// [[],[]]
|
|
|
|
// [1,2,3]
|
|
|
|
// [true,false,true]
|
2022-07-05 11:18:53 +08:00
|
|
|
if inputChar == commaToken && len(tmpStr) == 0 && (
|
|
|
|
// 对应 {"name":"zhangsan", "age":"18"}
|
|
|
|
(nil != preNode && preNode.Val == keyLeftRightToken) ||
|
2022-07-04 23:17:02 +08:00
|
|
|
// 对应[{"name":"zhangsan", "age":"18"}, {"name":"zhangsan", "age":"18"}]
|
|
|
|
(nil != preNode && preNode.Val == objectRightToken) ||
|
|
|
|
// 对应[[],[]]
|
|
|
|
(nil != preNode && preNode.Val == listRightToken) ||
|
|
|
|
// 对应 [true,false,true] / [1,2,3] / [1,true,2,false]
|
2022-07-05 11:18:53 +08:00
|
|
|
(nil != preNode && (preNode.Val == listLeftToken || preNode.Val == commaToken) && (tmpStrType == "number" || tmpStr == "bool"))) { // 对应
|
2022-07-04 23:17:02 +08:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// { 可能出现的情况
|
|
|
|
// {}
|
|
|
|
// [{}] [{}, {}]
|
|
|
|
// {"person": {}}
|
|
|
|
if inputChar == objectLeftToken && len(tmpStr) == 0 &&
|
|
|
|
(nil == preNode || // 对应 {}
|
|
|
|
(nil != preNode && preNode.Val == listLeftToken) || // 对应 [{}]
|
|
|
|
(nil != preNode && preNode.Val == colonToken) || // 对应 {"person": {}}
|
|
|
|
(nil != preNode && preNode.Val == commaToken)) { // 对应 [{}, {}]
|
|
|
|
// { 是关键字
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// } 可能出出现的情况
|
|
|
|
// {}
|
|
|
|
// [{}]
|
|
|
|
// {"name":"zhangsan"}
|
|
|
|
// {"person": {"name":"zhangsan"}}
|
|
|
|
// {"person": {"name":"zhangsan", "age": 18}}
|
|
|
|
// {"person": {"work":true}}
|
|
|
|
// {"person": {"like":1}}
|
2022-07-04 23:28:12 +08:00
|
|
|
// {"person_list": [{"like":1}]}
|
2022-07-04 23:17:02 +08:00
|
|
|
if inputChar == objectRightToken && len(tmpStr) == 0 && (
|
|
|
|
// 对应 {}, [{}]
|
|
|
|
(nil != preNode && preNode.Val == objectLeftToken) ||
|
|
|
|
// 对应 {"name":"zhangsan"}
|
|
|
|
(nil != preNode && preNode.Val == keyLeftRightToken) ||
|
|
|
|
// 对应 {"person": {"name":"zhangsan"}}
|
|
|
|
(nil != preNode && preNode.Val == objectRightToken)) ||
|
|
|
|
// 对应 {"person": {"work":true}} / {"person": {"like":1}}
|
2022-07-04 23:28:12 +08:00
|
|
|
(nil != preNode && preNode.Val == colonToken && (tmpStr == "number" || tmpStr == "bool")) ||
|
|
|
|
// 对应 {"person_list": [{"like":1}]}
|
|
|
|
(nil != preNode && preNode.Val == listRightToken) {
|
2022-07-04 23:17:02 +08:00
|
|
|
// } 是关键字
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// [ 可能出现的场景
|
|
|
|
// []
|
|
|
|
// [[],[]]
|
|
|
|
// "a": []
|
2022-07-05 11:18:53 +08:00
|
|
|
if inputChar == listLeftToken && len(tmpStr) == 0 && (nil == preNode || // 对应 []
|
2022-07-04 23:17:02 +08:00
|
|
|
(nil != preNode && preNode.Val == listLeftToken) || // 对应 [[],[]]
|
|
|
|
(nil != preNode && preNode.Val == colonToken)) { // 对应 "a": []
|
|
|
|
// [ 是关键字
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// ] 可能出现的场景
|
|
|
|
// []
|
|
|
|
// [[],[]]
|
|
|
|
// [{}, {}]
|
|
|
|
// [1,2,3]
|
|
|
|
// [true, false]
|
|
|
|
// ["", "" ]
|
2022-07-05 11:18:53 +08:00
|
|
|
if inputChar == listRightToken && len(tmpStr) == 0 && (
|
2022-07-04 23:17:02 +08:00
|
|
|
//对应 []
|
|
|
|
(nil != preNode && preNode.Val == listLeftToken) ||
|
|
|
|
// 对应 [[],[]]
|
|
|
|
(nil != preNode && preNode.Val == listRightToken) ||
|
|
|
|
// [true, false] /
|
|
|
|
(nil != preNode && preNode.Val == objectRightToken) ||
|
|
|
|
// 对应 [{}, {}] / [1,2,3]
|
|
|
|
(nil != preNode && (tmpStrType == "number" || tmpStrType == "bool")) ||
|
|
|
|
// 对应 ["", "" ]
|
|
|
|
(nil != preNode && preNode.Val == keyLeftRightToken)) {
|
2022-07-05 11:18:53 +08:00
|
|
|
return true
|
2022-07-04 23:17:02 +08:00
|
|
|
}
|
2022-07-04 18:19:04 +08:00
|
|
|
return false
|
|
|
|
}
|
2022-07-04 23:17:02 +08:00
|
|
|
|
|
|
|
func (l *lexical) getTpmStrType(tmpStr string) string {
|
|
|
|
var preNode *lexicalNode
|
|
|
|
if len(l.lexicalResult) > 0 {
|
|
|
|
preNode = l.lexicalResult[len(l.lexicalResult)-1]
|
|
|
|
}
|
|
|
|
|
|
|
|
// 数字只有一个场景 {"age": 18},多以若是数字, 则 前一次解析必为关键字 :
|
|
|
|
if nil != preNode && preNode.Val == colonToken {
|
|
|
|
// 判断是否可转数字
|
|
|
|
var floatVal float64
|
|
|
|
if err := util.ConvertAssign(&floatVal, tmpStr); nil == err {
|
|
|
|
return "number"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 判断是否为 bool
|
|
|
|
// bool 只有一个场景 {"work": true/false},多以若是数字, 则 前一次解析必为关键字 :
|
|
|
|
if nil != preNode && preNode.Val == colonToken {
|
|
|
|
// 判断是否可转数字
|
|
|
|
var boolVal bool
|
|
|
|
if err := util.ConvertAssign(&boolVal, tmpStr); nil == err {
|
|
|
|
return "bool"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "string"
|
|
|
|
}
|