sjson #1
64
define.go
64
define.go
@ -7,63 +7,15 @@
|
||||
// Date : 2022-07-04 18:02
|
||||
package filter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/util"
|
||||
)
|
||||
|
||||
// jsonNode json语法树节点定义
|
||||
// MapRule 映射规则
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:06 2022/7/4
|
||||
type jsonNode struct {
|
||||
Name string // 节点名称
|
||||
Parent *jsonNode // 父节点
|
||||
Son *jsonNode // 子节点
|
||||
PreBrother *jsonNode // 前一个兄弟节点
|
||||
NextBrother *jsonNode // 下一个兄弟节点
|
||||
Val interface{} // 节点的值
|
||||
Type string // 数据类型
|
||||
// Date : 12:21 2022/7/4
|
||||
type MapRule struct {
|
||||
SourcePath string `json:"source_path"` // 原路径
|
||||
MapPath string `json:"map_path"` // 映射路径
|
||||
Required bool `json:"required"` // 必须存在
|
||||
DataType string `json:"data_type"` // 数据类型
|
||||
DefaultValue string `json:"default_value"` // 默认值, 以字符串传入, 会转换成 DataType
|
||||
}
|
||||
|
||||
// lexicalNode 词法分析的节点
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:02 2022/7/4
|
||||
type lexicalNode struct {
|
||||
Val interface{} // 词法分析出来的词
|
||||
Type string // 值得类型
|
||||
Show bool // 这个值是否对外呈现
|
||||
IsToken bool // 是否为关键字
|
||||
OutputFormat string // 对外输出的格式
|
||||
}
|
||||
|
||||
// ValStr 值转为字符串
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:10 2022/7/5
|
||||
func (l *lexicalNode) ValStr() string {
|
||||
if l.Type == "number" {
|
||||
var str string
|
||||
_ = util.ConvertAssign(&str, l.Val)
|
||||
return str
|
||||
}
|
||||
return fmt.Sprintf("%v", l.Val)
|
||||
}
|
||||
|
||||
const (
|
||||
// NodeTypeNumber 数据类型
|
||||
NodeTypeNumber = "number"
|
||||
// NodeTypeBool bool 类型
|
||||
NodeTypeBool = "bool"
|
||||
// NodeTypeString 字符串类型
|
||||
NodeTypeString = "string"
|
||||
// NodeTypeObject kv 对象类型
|
||||
NodeTypeObject = "object"
|
||||
// NodeTypeList list类型
|
||||
NodeTypeList = "list"
|
||||
)
|
||||
|
76
filter.go
76
filter.go
@ -8,28 +8,16 @@
|
||||
package filter
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/tidwall/sjson"
|
||||
"strings"
|
||||
|
||||
"git.zhangdeman.cn/zhangdeman/util"
|
||||
"github.com/Jeffail/gabs"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// MapRule 映射规则
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 12:21 2022/7/4
|
||||
type MapRule struct {
|
||||
SourcePath string `json:"source_path"` // 原路径
|
||||
MapPath string `json:"map_path"` // 映射路径
|
||||
Required bool `json:"required"` // 必须存在
|
||||
DataType string `json:"data_type"` // 数据类型
|
||||
DefaultValue string `json:"default_value"` // 默认值, 以字符串传入, 会转换成 DataType
|
||||
}
|
||||
|
||||
// NewFilter 过滤器实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
@ -38,8 +26,8 @@ type MapRule struct {
|
||||
func NewFilter(sourceData string, filterRuleList []MapRule) *filter {
|
||||
return &filter{
|
||||
sourceData: sourceData,
|
||||
formatResult: "{}",
|
||||
filterRuleList: filterRuleList,
|
||||
jsonObj: &gabs.Container{},
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,8 +38,8 @@ func NewFilter(sourceData string, filterRuleList []MapRule) *filter {
|
||||
// Date : 11:58 2022/7/4
|
||||
type filter struct {
|
||||
sourceData string
|
||||
formatResult string
|
||||
filterRuleList []MapRule
|
||||
jsonObj *gabs.Container // 生成的json对象实例
|
||||
}
|
||||
|
||||
// Deal ...
|
||||
@ -59,27 +47,66 @@ type filter struct {
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 11:59 2022/7/4
|
||||
func (f *filter) Deal() ([]byte, error) {
|
||||
func (f *filter) Deal() error {
|
||||
var (
|
||||
err error
|
||||
formatVal interface{}
|
||||
)
|
||||
|
||||
for _, rule := range f.filterRuleList {
|
||||
if strings.Contains(rule.SourcePath, "[]") {
|
||||
// 对于list的处理
|
||||
continue
|
||||
}
|
||||
sourceResult := gjson.Get(f.sourceData, rule.SourcePath)
|
||||
sourceVal := sourceResult.String()
|
||||
var (
|
||||
sourceVal string
|
||||
)
|
||||
|
||||
if !sourceResult.Exists() {
|
||||
// 不存在, 使用默认值
|
||||
sourceVal = rule.DefaultValue
|
||||
} else {
|
||||
sourceVal = sourceResult.String()
|
||||
}
|
||||
formatVal, err := f.getValue(rule.DataType, sourceVal)
|
||||
if nil != err {
|
||||
return nil, fmt.Errorf("%s = %v can not convert to %s : %s", rule.SourcePath, sourceResult.Value(), rule.DataType, err.Error())
|
||||
if formatVal, err = f.getValue(rule.DataType, sourceVal); nil != err {
|
||||
return fmt.Errorf("%s = %v can not convert to %s : %s", rule.SourcePath, sourceResult.Value(), rule.DataType, err.Error())
|
||||
}
|
||||
if _, err := f.jsonObj.SetP(formatVal, rule.MapPath); nil != err {
|
||||
return nil, fmt.Errorf("%s set val = %v fail : %s", rule.MapPath, formatVal, err.Error())
|
||||
if _, err = sjson.Set(f.formatResult, rule.MapPath, formatVal); nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return f.jsonObj.EncodeJSON(), nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// String 获取格式化之后的字符串
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 21:18 2022/12/31
|
||||
func (f *filter) String() string {
|
||||
return f.formatResult
|
||||
}
|
||||
|
||||
// Byte 获取格式化之后的字节数组
|
||||
//
|
||||
// Author : zhangdeman001@ke.com<张德满>
|
||||
//
|
||||
// Date : 21:18 2022/12/31
|
||||
func (f *filter) Byte() []byte {
|
||||
return []byte(f.String())
|
||||
}
|
||||
|
||||
// Parse 解析返回结果
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 21:20 2022/12/31
|
||||
func (f *filter) Parse(receiver interface{}) error {
|
||||
if nil == receiver {
|
||||
return errors.New("receiver is nil")
|
||||
}
|
||||
return json.Unmarshal(f.Byte(), receiver)
|
||||
}
|
||||
|
||||
// getValue 获取值
|
||||
@ -141,4 +168,3 @@ func (f *filter) getValue(dataType string, defaultValue string) (interface{}, er
|
||||
return nil, errors.New(dataType + " is not support!")
|
||||
}
|
||||
}
|
||||
|
||||
|
3
go.mod
3
go.mod
@ -11,9 +11,10 @@ require (
|
||||
|
||||
require (
|
||||
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/stretchr/testify v1.8.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
|
5
go.sum
5
go.sum
@ -1,5 +1,3 @@
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20220704053716-ec9271c0f350 h1:y54/TJ7SCSG1LlKrX7QebDBdv+JoEl8JVs2kEqFoEXs=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20220704053716-ec9271c0f350/go.mod h1:aAIhnUdQewLipl4bddewAsAeSLST9SRvgTcPN5ITkAQ=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221021061434-e68b22a6e106 h1:xiiN+rLtBbDGRUbipVuwI1j2iRhuL3ejSm+EnDxzVMk=
|
||||
git.zhangdeman.cn/zhangdeman/util v0.0.0-20221021061434-e68b22a6e106/go.mod h1:zTir/0IWdK3E7n0GiaogyWHADAQnBtTdl2I6Z2/OPqw=
|
||||
github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
|
||||
@ -9,7 +7,6 @@ github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIg
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-ini/ini v1.66.6 h1:h6k2Bb0HWS/BXXHCXj4QHjxPmlIU4NK+7MuLp9SD+4k=
|
||||
github.com/go-ini/ini v1.66.6/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||
@ -24,14 +21,12 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
|
||||
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
|
304
lexical.go
304
lexical.go
@ -1,304 +0,0 @@
|
||||
// Package filter ...
|
||||
//
|
||||
// Description : JSON 词法分析
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022-07-04 17:52
|
||||
package filter
|
||||
|
||||
import (
|
||||
"git.zhangdeman.cn/zhangdeman/util"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// NewLexical 获取实例
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 20:52 2022/7/4
|
||||
func NewLexical(jsonData string) *lexical {
|
||||
return &lexical{
|
||||
jsonData: jsonData,
|
||||
lexicalResult: make([]*lexicalNode, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// lexical 词法解析
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 20:42 2022/7/4
|
||||
type lexical struct {
|
||||
jsonData string
|
||||
keyLeftRightTokenCnt int
|
||||
lexicalResult []*lexicalNode
|
||||
}
|
||||
|
||||
// Parse 解析词法
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:11 2022/7/4
|
||||
func (l *lexical) Parse() error {
|
||||
// mt.Println(jsonData)
|
||||
if len(l.jsonData) < 2 {
|
||||
return errors.New("input data is not json")
|
||||
}
|
||||
tmpStr := ""
|
||||
for _, itemChar := range l.jsonData {
|
||||
currentChar := string(itemChar)
|
||||
tmpRealVal, tmpStrType := l.getTmpStrType(tmpStr)
|
||||
if l.inputCharIsToken(currentChar, tmpStr, tmpStrType) {
|
||||
if currentChar == keyLeftRightToken {
|
||||
// 双引号计数
|
||||
l.keyLeftRightTokenCnt++
|
||||
}
|
||||
// 是关键词
|
||||
if len(tmpStr) > 0 {
|
||||
l.lexicalResult = append(l.lexicalResult, &lexicalNode{
|
||||
Val: tmpRealVal,
|
||||
IsToken: false,
|
||||
Type: tmpStrType,
|
||||
})
|
||||
}
|
||||
l.lexicalResult = append(l.lexicalResult, &lexicalNode{
|
||||
Val: currentChar,
|
||||
IsToken: true,
|
||||
Type: "string",
|
||||
})
|
||||
tmpStr = ""
|
||||
} else {
|
||||
// 不是关键词, 继续向后走
|
||||
if currentChar == " " && l.keyLeftRightTokenCnt%2 == 0 {
|
||||
// 当前字符是空格, 只有在 "" 之间方才有效 , 关键字之间的空格, 忽略即可
|
||||
continue
|
||||
}
|
||||
if (currentChar == "\n" || currentChar == "\t") && (l.keyLeftRightTokenCnt%2 == 0 || tmpStrType == "number" || tmpStrType == "bool") {
|
||||
// 数字或者 bool 之后的 \n \t 无意义 , 不在 "" 之间也无意义
|
||||
continue
|
||||
}
|
||||
tmpStr = tmpStr + currentChar
|
||||
}
|
||||
}
|
||||
|
||||
if len(tmpStr) > 0 {
|
||||
l.lexicalResult = append(l.lexicalResult, &lexicalNode{
|
||||
Val: tmpStr,
|
||||
IsToken: false,
|
||||
Type: NodeTypeString,
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// inputCharIsToken 输入字符是否为关键字
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 18:15 2022/7/4
|
||||
func (l *lexical) inputCharIsToken(inputChar string, tmpStr string, tmpStrType string) bool {
|
||||
tokenList := []string{
|
||||
// list 类型起始
|
||||
listLeftToken,
|
||||
// listRight list 类型结束
|
||||
listRightToken,
|
||||
// 对象起始
|
||||
objectLeftToken,
|
||||
// 对象结束
|
||||
objectRightToken,
|
||||
// key 值的起始
|
||||
keyLeftRightToken,
|
||||
// 转义符
|
||||
// escapeCharacterToken,
|
||||
// 冒号
|
||||
colonToken,
|
||||
// 逗号
|
||||
commaToken,
|
||||
}
|
||||
preCheck := false
|
||||
for _, item := range tokenList {
|
||||
if item == inputChar {
|
||||
preCheck = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !preCheck {
|
||||
// 输入一定不是关键字
|
||||
return false
|
||||
}
|
||||
|
||||
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 个 或者 偶数个转义符, " 是关键字
|
||||
if inputChar == keyLeftRightToken && escapeCharacterTokenCnt%2 == 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
var preNode *lexicalNode
|
||||
if len(l.lexicalResult) > 0 {
|
||||
preNode = l.lexicalResult[len(l.lexicalResult)-1]
|
||||
}
|
||||
|
||||
if inputChar == colonToken && nil != preNode && preNode.ValStr() == keyLeftRightToken && l.keyLeftRightTokenCnt > 0 && l.keyLeftRightTokenCnt%2 == 0 {
|
||||
// : 必须出现在偶数 " 之后才是关键字
|
||||
return true
|
||||
}
|
||||
|
||||
// , 是关键字的场景
|
||||
// {"name":"zhangsan", "age":"18"}
|
||||
// [{"name":"zhangsan", "age":"18"}, {"name":"zhangsan", "age":"18"}]
|
||||
// [[],[]]
|
||||
// [1,2,3]
|
||||
// [true,false,true]
|
||||
if inputChar == commaToken && (
|
||||
// 对应 {"name":"zhangsan", "age":"18"}
|
||||
(nil != preNode && preNode.ValStr() == keyLeftRightToken) ||
|
||||
// 对应[{"name":"zhangsan", "age":"18"}, {"name":"zhangsan", "age":"18"}]
|
||||
(nil != preNode && preNode.ValStr() == objectRightToken) ||
|
||||
// 对应[[],[]]
|
||||
(nil != preNode && preNode.ValStr() == listRightToken) ||
|
||||
// 对应 [true,false,true] / [1,2,3] / [1,true,2,false]
|
||||
(nil != preNode && (preNode.ValStr() == colonToken || preNode.ValStr() == listLeftToken || preNode.ValStr() == commaToken) && (tmpStrType == "number" || tmpStrType == "bool"))) { // 对应
|
||||
return true
|
||||
}
|
||||
|
||||
// { 可能出现的情况
|
||||
// {}
|
||||
// [{}] [{}, {}]
|
||||
// {"person": {}}
|
||||
if inputChar == objectLeftToken && len(tmpStr) == 0 &&
|
||||
(nil == preNode || // 对应 {}
|
||||
(nil != preNode && preNode.ValStr() == listLeftToken) || // 对应 [{}]
|
||||
(nil != preNode && preNode.ValStr() == colonToken) || // 对应 {"person": {}}
|
||||
(nil != preNode && preNode.ValStr() == commaToken)) { // 对应 [{}, {}]
|
||||
// { 是关键字
|
||||
return true
|
||||
}
|
||||
|
||||
// } 可能出出现的情况
|
||||
// {}
|
||||
// [{}]
|
||||
// {"name":"zhangsan"}
|
||||
// {"person": {"name":"zhangsan"}}
|
||||
// {"person": {"name":"zhangsan", "age": 18}}
|
||||
// {"person": {"work":true}}
|
||||
// {"person": {"like":1}}
|
||||
// {"person_list": [{"like":1}]}
|
||||
if inputChar == objectRightToken && len(tmpStr) == 0 && (
|
||||
// 对应 {}, [{}]
|
||||
(nil != preNode && preNode.ValStr() == objectLeftToken) ||
|
||||
// 对应 {"name":"zhangsan"}
|
||||
(nil != preNode && preNode.ValStr() == keyLeftRightToken) ||
|
||||
// 对应 {"person": {"name":"zhangsan"}}
|
||||
(nil != preNode && preNode.ValStr() == objectRightToken)) ||
|
||||
// 对应 {"person": {"work":true}} / {"person": {"like":1}}
|
||||
(nil != preNode && preNode.ValStr() == colonToken && (tmpStr == "number" || tmpStr == "bool")) ||
|
||||
// 对应 {"person_list": [{"like":1}]}
|
||||
(nil != preNode && preNode.ValStr() == listRightToken) {
|
||||
// } 是关键字
|
||||
return true
|
||||
}
|
||||
|
||||
// [ 可能出现的场景
|
||||
// []
|
||||
// [[],[]]
|
||||
// "a": []
|
||||
if inputChar == listLeftToken && len(tmpStr) == 0 && (nil == preNode || // 对应 []
|
||||
(nil != preNode && preNode.ValStr() == listLeftToken) || // 对应 [[],[]]
|
||||
(nil != preNode && preNode.ValStr() == colonToken)) { // 对应 "a": []
|
||||
// [ 是关键字
|
||||
return true
|
||||
}
|
||||
|
||||
// ] 可能出现的场景
|
||||
// []
|
||||
// [[],[]]
|
||||
// [{}, {}]
|
||||
// [1,2,3]
|
||||
// [true, false]
|
||||
// ["", "" ]
|
||||
if inputChar == listRightToken && len(tmpStr) == 0 && (
|
||||
//对应 []
|
||||
(nil != preNode && preNode.ValStr() == listLeftToken) ||
|
||||
// 对应 [[],[]]
|
||||
(nil != preNode && preNode.ValStr() == listRightToken) ||
|
||||
// [true, false] /
|
||||
(nil != preNode && preNode.ValStr() == objectRightToken) ||
|
||||
// 对应 [{}, {}] / [1,2,3]
|
||||
(nil != preNode && (tmpStrType == "number" || tmpStrType == "bool")) ||
|
||||
// 对应 ["", "" ]
|
||||
(nil != preNode && preNode.ValStr() == keyLeftRightToken)) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (l *lexical) getTmpStrType(tmpStr string) (interface{}, string) {
|
||||
var preNode *lexicalNode
|
||||
if len(l.lexicalResult) > 0 {
|
||||
preNode = l.lexicalResult[len(l.lexicalResult)-1]
|
||||
}
|
||||
|
||||
// 数字只有一个场景 {"age": 18},多以若是数字, 则 前一次解析必为关键字 :
|
||||
if nil != preNode && preNode.ValStr() == colonToken {
|
||||
// 判断是否可转数字
|
||||
var floatVal float64
|
||||
if err := util.ConvertAssign(&floatVal, tmpStr); nil == err {
|
||||
return floatVal, "number"
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否为 bool
|
||||
// bool 只有一个场景 {"work": true/false},多以若是数字, 则 前一次解析必为关键字 :
|
||||
if nil != preNode && preNode.ValStr() == colonToken {
|
||||
// 判断是否可转数字
|
||||
var boolVal bool
|
||||
if err := util.ConvertAssign(&boolVal, tmpStr); nil == err {
|
||||
return boolVal, "bool"
|
||||
}
|
||||
}
|
||||
return tmpStr, "string"
|
||||
}
|
||||
|
||||
// String 将解析后的词法, 转换为字符串
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:34 2022/7/5
|
||||
func (l *lexical) String() string {
|
||||
str := ""
|
||||
for _, item := range l.lexicalResult {
|
||||
str = str + item.ValStr()
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// Result 词法分析的结果
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:55 2022/7/5
|
||||
func (l *lexical) Result() []*lexicalNode {
|
||||
return l.lexicalResult
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
// Package filter ...
|
||||
//
|
||||
// Description : filter ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022-07-04 18:13
|
||||
package filter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_parseLexical(t *testing.T) {
|
||||
jsonData := `{
|
||||
"start" : 123456,
|
||||
"name" : "zhangsan",
|
||||
"age":"18",
|
||||
"extension":{
|
||||
"sex":"man",
|
||||
"height":"180"
|
||||
},
|
||||
"teacher_list":[
|
||||
{
|
||||
"name":"t1",
|
||||
"age":"11"
|
||||
},
|
||||
{
|
||||
"name":"t2",
|
||||
"age":"12"
|
||||
}
|
||||
]
|
||||
}`
|
||||
//jsonData = `{"name":"zhangsan","age":"18","extension":{"sex":"man","height":"180"},"teacher_list":[{"name":"t1","age":"11"},{"name":"t2","age":"12"}]}`
|
||||
|
||||
instance := NewLexical(jsonData)
|
||||
_ = instance.Parse()
|
||||
fmt.Println(instance.String())
|
||||
}
|
153
syntax.go
153
syntax.go
@ -1,153 +0,0 @@
|
||||
// Package filter ...
|
||||
//
|
||||
// Description : 语法分析
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022-07-04 17:53
|
||||
package filter
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// NewSyntax 构建JSON语法树
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 14:33 2022/7/5
|
||||
func NewSyntax(jsonData string) *syntax {
|
||||
return &syntax{
|
||||
lexicalInstance: NewLexical(jsonData),
|
||||
syntaxResult: nil,
|
||||
}
|
||||
}
|
||||
|
||||
type syntax struct {
|
||||
// 词法分析实例
|
||||
lexicalInstance *lexical
|
||||
// 词法分析结果
|
||||
lexicalResult []*lexicalNode
|
||||
// 语法分析结果
|
||||
syntaxResult *jsonNode
|
||||
}
|
||||
|
||||
// Parse 构建语法树
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 16:35 2022/7/5
|
||||
func (s *syntax) Parse() error {
|
||||
if err := s.lexicalInstance.Parse(); nil != err {
|
||||
// 词法解析失败
|
||||
return err
|
||||
}
|
||||
s.lexicalResult = s.lexicalInstance.Result()
|
||||
if len(s.lexicalResult) == 0 {
|
||||
return errors.New("词法解析无任何结果")
|
||||
}
|
||||
// TODO : 循环处理
|
||||
generateNode, lastIdx, err := s.generateJSONNode(0)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
if lastIdx >= len(s.lexicalResult) {
|
||||
// 词法处理完成
|
||||
return nil
|
||||
}
|
||||
if nil == s.syntaxResult {
|
||||
s.syntaxResult = generateNode
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateJSONNode 构建 JSONNode, 参数 : 从那个索引开始处理 返回值 : 当前 json 节点, 下次从那个索引开始处理, 异常
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 16:58 2022/7/5
|
||||
func (s *syntax) generateJSONNode(currentLexicalIdx int) (*jsonNode, int, error) {
|
||||
generateJSONNode := &jsonNode{
|
||||
Name: "",
|
||||
Parent: nil,
|
||||
Son: nil,
|
||||
PreBrother: nil,
|
||||
NextBrother: nil,
|
||||
Val: nil,
|
||||
Type: "",
|
||||
}
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() == objectLeftToken {
|
||||
// 对象的起始, 类型一定为对象
|
||||
generateJSONNode.Type = NodeTypeObject
|
||||
|
||||
// 下一个必定为 " (原因: 词法分析时, 已经过滤掉无用的空格换行符等, JSON数据已压缩成单行字符串)
|
||||
currentLexicalIdx++
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() != keyLeftRightToken {
|
||||
// 不是 " 号, 说明数据格式非法
|
||||
return nil, currentLexicalIdx, errors.New("JSON格式非法")
|
||||
}
|
||||
|
||||
// 在下一个必定是 json 的 key
|
||||
currentLexicalIdx++
|
||||
generateJSONNode.Name = s.lexicalResult[currentLexicalIdx].ValStr()
|
||||
|
||||
// 在下一个必定是 "
|
||||
currentLexicalIdx++
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() != keyLeftRightToken {
|
||||
// 不是 " 号, 说明数据格式非法
|
||||
return nil, currentLexicalIdx, errors.New("JSON格式非法")
|
||||
}
|
||||
|
||||
// 在下一个必定是 :
|
||||
currentLexicalIdx++
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() != colonToken {
|
||||
// 不是 : 号, 说明数据格式非法
|
||||
return nil, currentLexicalIdx, errors.New("JSON格式非法")
|
||||
}
|
||||
|
||||
// 到了取值部分, 具体分析是简单 k -> v or k -> object or k -> list
|
||||
currentLexicalIdx++
|
||||
if s.lexicalResult[currentLexicalIdx].IsToken &&
|
||||
s.lexicalResult[currentLexicalIdx].ValStr() != keyLeftRightToken {
|
||||
// TODO : 是关键字, 且不是 " 号 , 说明不是简单KV, 后续具体处理
|
||||
return generateJSONNode, currentLexicalIdx, nil
|
||||
}
|
||||
// 简单KV, 下一个必定是取值
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() == keyLeftRightToken {
|
||||
// 双引号
|
||||
currentLexicalIdx++
|
||||
generateJSONNode.Val = s.lexicalResult[currentLexicalIdx].ValStr()
|
||||
// 跳过字符串闭合的 " 号
|
||||
currentLexicalIdx = currentLexicalIdx + 2
|
||||
// 判断 闭合 " 之后 是不是 , / ] / }
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() == commaToken {
|
||||
// 跳过 分割的 ,
|
||||
currentLexicalIdx++
|
||||
} else {
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() == objectRightToken ||
|
||||
s.lexicalResult[currentLexicalIdx].ValStr() == listRightToken {
|
||||
// 跳过整体对象的闭合标签
|
||||
currentLexicalIdx++
|
||||
}
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() == commaToken {
|
||||
// 还是 ,
|
||||
currentLexicalIdx++
|
||||
}
|
||||
}
|
||||
} else {
|
||||
generateJSONNode.Val = s.lexicalResult[currentLexicalIdx].Val
|
||||
generateJSONNode.Type = s.lexicalResult[currentLexicalIdx].Type
|
||||
currentLexicalIdx++
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() == objectRightToken ||
|
||||
s.lexicalResult[currentLexicalIdx].ValStr() == listRightToken {
|
||||
// 跳过整体对象的闭合标签
|
||||
currentLexicalIdx++
|
||||
}
|
||||
if s.lexicalResult[currentLexicalIdx].ValStr() == commaToken {
|
||||
// 还是 ,
|
||||
currentLexicalIdx++
|
||||
}
|
||||
}
|
||||
}
|
||||
return generateJSONNode, currentLexicalIdx, nil
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
// Package filter ...
|
||||
//
|
||||
// Description : filter ...
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022-07-05 17:43
|
||||
package filter
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_syntax_Parse(t *testing.T) {
|
||||
jsonData := `{
|
||||
"start" : 123456,
|
||||
"name" : "zhangsan",
|
||||
"age":"18",
|
||||
"extension":{
|
||||
"sex":"man",
|
||||
"height":"180"
|
||||
},
|
||||
"teacher_list":[
|
||||
{
|
||||
"name":"t1",
|
||||
"age":"11"
|
||||
},
|
||||
{
|
||||
"name":"t2",
|
||||
"age":"12"
|
||||
}
|
||||
]
|
||||
}`
|
||||
//jsonData = `{"name":"zhangsan","age":"18","extension":{"sex":"man","height":"180"},"teacher_list":[{"name":"t1","age":"11"},{"name":"t2","age":"12"}]}`
|
||||
|
||||
instance := NewSyntax(jsonData)
|
||||
_ = instance.Parse()
|
||||
}
|
27
token.go
27
token.go
@ -1,27 +0,0 @@
|
||||
// Package filter ...
|
||||
//
|
||||
// Description : 关键词定义
|
||||
//
|
||||
// Author : go_developer@163.com<白茶清欢>
|
||||
//
|
||||
// Date : 2022-07-04 17:53
|
||||
package filter
|
||||
|
||||
const (
|
||||
// list 类型起始
|
||||
listLeftToken = "["
|
||||
// listRight list 类型结束
|
||||
listRightToken = "]"
|
||||
// 对象起始
|
||||
objectLeftToken = "{"
|
||||
// 对象结束
|
||||
objectRightToken = "}"
|
||||
// key 值的起始
|
||||
keyLeftRightToken = "\""
|
||||
// 转义符
|
||||
escapeCharacterToken = "\\"
|
||||
// 冒号
|
||||
colonToken = ":"
|
||||
// 逗号
|
||||
commaToken = ","
|
||||
)
|
Loading…
Reference in New Issue
Block a user