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 } }