Files
jaeson/jsonParse.go

321 lines
6.7 KiB
Go

package jaeson
import (
"strconv"
"gitea.cozeon.cloud/anand.ekka-ext/parser"
"github.com/antlr/antlr4/runtime/Go/antlr"
)
type stackElem struct {
jsObj *JSONObject
jsArr *JSONArray
hasJsObj bool
hasJsArr bool
}
func (v *stackElem) Init() {
v.hasJsObj = false
v.hasJsArr = false
}
func (v *stackElem) GetJsObj() *JSONObject {
return v.jsObj
}
func (v *stackElem) GetJsArr() *JSONArray {
return v.jsArr
}
func (v *stackElem) GetHasJsObj() bool {
return v.hasJsObj
}
func (v *stackElem) GetHasJsArr() bool {
return v.hasJsArr
}
func (v *stackElem) PutJSONObject(jsnObj *JSONObject) {
v.hasJsObj = true
v.hasJsArr = false
v.jsObj = jsnObj
}
func (v *stackElem) PutJSONArray(jsnArr *JSONArray) {
v.hasJsObj = false
v.hasJsArr = true
v.jsArr = jsnArr
}
type jsonListener struct {
*parser.BaseJSONListener
topJsObj *JSONObject
currJsObj *JSONObject
currJsArr *JSONArray
currKey string
childJsObj *JSONObject
childJsArr *JSONArray
foundKeyOfPair bool
jsonStartFound bool
topObjCreated bool
arrStart bool
parentObjStack []*stackElem
stckElemPointer int
topJsArr *JSONArray
topArrCreated bool
}
func (s *jsonListener) GetLastElem() *stackElem {
return s.parentObjStack[s.stckElemPointer-1]
}
func (s *jsonListener) DeleteLastElem() {
s.parentObjStack[s.stckElemPointer-1] = nil
s.stckElemPointer -= 1
}
func (s *jsonListener) AddJSONObjToStack(jsObj *JSONObject) {
tmpStckElem := new(stackElem)
tmpStckElem.Init()
s.stckElemPointer += 1
if s.stckElemPointer > len(s.parentObjStack) {
s.parentObjStack = append(s.parentObjStack, tmpStckElem)
} else {
s.parentObjStack[s.stckElemPointer-1] = tmpStckElem
}
tmpStckElem.PutJSONObject(jsObj)
}
func (s *jsonListener) AddJSONArrToStack(jsArr *JSONArray) {
tmpStckElem := new(stackElem)
tmpStckElem.Init()
s.stckElemPointer += 1
if s.stckElemPointer > len(s.parentObjStack) {
s.parentObjStack = append(s.parentObjStack, tmpStckElem)
} else {
s.parentObjStack[s.stckElemPointer-1] = tmpStckElem
}
tmpStckElem.PutJSONArray(jsArr)
}
//--------------- Json Enter-Exit ---------------//
func (s *jsonListener) EnterJson(ctx *parser.JsonContext) {
s.jsonStartFound = true
s.topObjCreated = false
s.stckElemPointer = 0
}
func (s *jsonListener) ExitJson(ctx *parser.JsonContext) {
// nothing needs to be implemented
}
//--------------- Obj Enter-Exit ---------------//
func (s *jsonListener) EnterObj(ctx *parser.ObjContext) {
if !s.topObjCreated && !s.topArrCreated {
s.topJsObj = new(JSONObject)
s.topJsObj.Init()
s.currJsObj = s.topJsObj
s.foundKeyOfPair = false
s.topObjCreated = true
s.arrStart = false
//initialize stack
s.parentObjStack = make([]*stackElem, 0)
//Add topJsObj to stack
s.AddJSONObjToStack(s.topJsObj)
} else {
s.childJsObj = new(JSONObject)
s.childJsObj.Init()
if s.arrStart {
s.currJsArr.PutJSONObject(s.childJsObj)
s.AddJSONArrToStack(s.currJsArr)
s.currJsObj = s.childJsObj
s.arrStart = false
} else {
s.currJsObj.PutJSONObject(s.currKey, s.childJsObj)
// might need stack up or append curr object in a LIFO stack,
// before takig on the new child object
s.AddJSONObjToStack(s.currJsObj)
s.currJsObj = s.childJsObj
}
}
}
func (s *jsonListener) ExitObj(ctx *parser.ObjContext) {
tmpPrevStckElem := s.GetLastElem()
if tmpPrevStckElem != nil {
if tmpPrevStckElem.GetHasJsObj() {
s.currJsObj = tmpPrevStckElem.GetJsObj()
s.arrStart = false
} else {
s.currJsArr = tmpPrevStckElem.GetJsArr()
s.arrStart = true
}
s.DeleteLastElem()
} //else {
// nothing needs to be implemented
//}
}
//--------------- Arr Enter-Exit ---------------//
// EnterArr is called when production arr is entered.
func (s *jsonListener) EnterArr(ctx *parser.ArrContext) {
if !s.topObjCreated && !s.topArrCreated {
s.topJsArr = new(JSONArray)
s.topJsArr.Init()
s.currJsArr = s.topJsArr
s.topArrCreated = true
s.arrStart = true
//initialize stack
s.parentObjStack = make([]*stackElem, 0)
//Add topJsArr to stack
s.AddJSONArrToStack(s.topJsArr)
} else {
if s.arrStart {
s.childJsArr = new(JSONArray)
s.childJsArr.Init()
//add currJsArr to stack
s.AddJSONArrToStack(s.currJsArr)
s.currJsArr.PutJSONArray(s.childJsArr)
s.currJsArr = s.childJsArr
} else {
s.currJsArr = new(JSONArray)
s.currJsArr.Init()
s.currJsObj.PutJSONArray(s.currKey, s.currJsArr)
s.AddJSONObjToStack(s.currJsObj)
}
}
s.arrStart = true
}
// ExitArr is called when production arr is exited.
func (s *jsonListener) ExitArr(ctx *parser.ArrContext) {
s.arrStart = false
tmpPrevStckElem := s.GetLastElem()
if tmpPrevStckElem.GetHasJsObj() {
s.currJsObj = tmpPrevStckElem.GetJsObj()
s.arrStart = false
} else {
s.currJsArr = tmpPrevStckElem.GetJsArr()
s.arrStart = true
}
s.DeleteLastElem()
}
//--------------- Pair Enter-Exit ---------------//
func (s *jsonListener) EnterPair(ctx *parser.PairContext) {
s.foundKeyOfPair = true
s.currKey = ctx.STRING().GetSymbol().GetText()
s.currKey = s.currKey[1 : len(s.currKey)-1]
}
func (s *jsonListener) ExitPair(ctx *parser.PairContext) {
s.foundKeyOfPair = false
}
//--------------- Value Enter-Exit ---------------//
func (s *jsonListener) EnterValue(ctx *parser.ValueContext) {
if ctx.STRING() != nil {
val0 := ctx.STRING().GetSymbol().GetText()
val1 := val0[1 : len(val0)-1]
if s.arrStart {
s.currJsArr.PutString(val1)
} else {
s.currJsObj.PutString(s.currKey, val1)
}
}else if ctx.NUMBER() != nil {
val0 := ctx.NUMBER().GetSymbol().GetText()
vali, erri := strconv.ParseInt(val0, 10, 64)
if erri != nil {
valf, errf := strconv.ParseFloat(val0, 64)
if errf == nil {
s.currJsObj.PutFloat(s.currKey, valf)
} else {
// neither int nor float. then what is it ?
}
}else{
s.currJsObj.PutInt(s.currKey, int(vali))
}
//s.currJsObj.PutInt(s.currKey, val1)
}else if ctx.Obj() != nil {
// nothing needs to be implemented
}else if ctx.BOOLEAN() != nil {
val0 := ctx.BOOLEAN().GetSymbol().GetText()
val1, _ := strconv.ParseBool(val0)
s.currJsObj.PutBool(s.currKey, val1)
}
s.foundKeyOfPair = false
}
func (s *jsonListener) ExitValue(ctx *parser.ValueContext) {
// nothing needs to be implemented
}
func UnmarshalJSON(jsonstr string) (*JSONObject, *JSONArray) {
is := antlr.NewInputStream(jsonstr)
// Create the Lexer
lexer := parser.NewJSONLexer(is)
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
// Create the Parser
p := parser.NewJSONParser(stream)
// Finally parse the expression
var jsonLstnr *jsonListener = new(jsonListener)
antlr.ParseTreeWalkerDefault.Walk(jsonLstnr, p.Json())
if jsonLstnr.topObjCreated {
return jsonLstnr.topJsObj, nil
} else {
return nil, jsonLstnr.topJsArr
}
}