Snippets

SeanB JSON Parsing

Updated by SeanB

File JSONParser.pkg Modified

  • Ignore whitespace
  • Hide word diff
 //***                                                                       ***
 //*** Author: Sean Bamforth                                                 ***
 //***         SELECT Computer Systems Ltd                                   ***
-//***         April / May 2011                                              ***
+//***         2011 - 2016                                                   ***
 //***                                                                       ***
 //*** Purpose:                                                              ***
 //***    JSON Client interface for talking to JSON / restful services.      ***
Updated by SeanB

File JSONParser.pkg Modified

  • Ignore whitespace
  • Hide word diff
             End
             
             Else If (sState = "objectvalue") Begin 
-                If (isWhiteSpace(Self,sToken)) Begin 
+                If ((isInsideQuote) and (isEscape)) Begin 
+                    Append sValue sToken 
+                    Move (False) to isEscape
+                End
+                Else If ((isInsideQuote) and (sToken="\") and (not(isEscape))) Begin 
+                    Move (True) to isEscape
+                    Append sValue sToken 
+                End
+                Else If (isWhiteSpace(Self,sToken)) Begin 
                     If (isInsideQuote) Append sValue sToken
                 End
                 Else If ((sToken = '"') and (iQuoteLevel = 0)) Begin 
             End
             
             Else If (sState = "objectvalue") Begin 
-                If (isWhiteSpace(Self,sToken)) Begin 
+                If ((isInsideQuote) and (isEscape)) Begin 
+                    Append sValue sToken 
+                    Move (False) to isEscape
+                End
+                Else If ((isInsideQuote) and (sToken="\") and (not(isEscape))) Begin 
+                    Move (True) to isEscape
+                    Append sValue sToken 
+                End
+                else If (isWhiteSpace(Self,sToken)) Begin 
                     If (isInsideQuote) Append sValue sToken
                 End
                 Else If ((sToken = '"') and (iQuoteLevel = 0)) Begin 
     
 End_Class
 
-Object oSelectJSON is a cSelectJSON 
-End_Object
Created by SeanB

File JSONParser.pkg Added

  • Ignore whitespace
  • Hide word diff
+//*****************************************************************************
+//*** json.pkg                                                              ***
+//***                                                                       ***
+//*** Author: Sean Bamforth                                                 ***
+//***         SELECT Computer Systems Ltd                                   ***
+//***         April / May 2011                                              ***
+//***                                                                       ***
+//*** Purpose:                                                              ***
+//***    JSON Client interface for talking to JSON / restful services.      ***
+//***                                                                       ***
+//*** License:                                                              ***
+//***    You're free to use and modify this library in your own projects.   ***
+//***    You're not free to redistribute this package without permission    ***
+//***    from SELECT Computer Systems.                                      ***
+//***                                                                       ***
+//*****************************************************************************
+
+//Description
+// cSelectJSON is the JSON Class, but there's a global object called oSelectJSON 
+// set psData to your JSON Structure (as a string)
+// You can directly access JSON Values via dot notation
+// e.g. get JSONValue of oSelectJSON "results[0].geometry.location.lat" to nLAT 
+// or you can pull the JSON structure into a tJSONDictionary and move through that. 
+
+//Usage examples (with google maps api): 
+//    string sData
+//    tJSONDictionary[] dctLocation
+//    string[] aStrings
+//    move '["statusCode":200,"statusDescription":"OK",numList={1,2,3,4}]' to sData
+//    set psData of oSelectJSON to sData //sData is a string containing a JSON Structure. 
+//    get JSONDictionary of oSelectJSON "" to dctLocation
+//    get JSONValue of oSelectJSON "statusCode" to iStatusCode
+//    get JSONValue of oSelectJSON "numlist" to aStrings
+//    showln dctLocation[0].sItem ":" dctLocation[0].sValue
+//    showln aStrings[0]
+//
+//    get GoogleMapsResult to sData
+//    set psData of oSelectJSON to sData //sData is a string containing a JSON Structure. 
+//    get JSONValue of oSelectJSON "results[0].geometry.location.lat" to nLAT 
+//    get JSONDictionary of oSelectJSON "results[0].geometry.location to dctLocation  //array of tJSONDictionary
+//    get JSONArray of oSelectJSON "results" to aStrings  //array of string
+//
+//    Set psData of oSelectJSON to (psDirections(oDirectionReader))
+//    Get JSONArray of oSelectJSON "routes[0].legs" to aLegs
+//    Move (SizeOfArray(aLegs)) to iMax 
+//    For iPos from 0 to (iMax-1)
+//        Set psData of oSelectJSON to  aLegs[iPos] 
+//        Get JSONArray of oSelectJSON "steps" to aSteps 
+//        showln aSteps[0]
+//    Loop
+
+//Support 
+//There's no support. Sorry. 
+
+Struct tJSONDictionary
+    String sItem 
+    String sValue 
+End_Struct
+
+Object oJSON is a cObject 
+    Property String[] pCacheValueArray
+    Property String psArrayCacheText
+    Property tJSONDictionary[] pCacheDictionary
+    Property String psDictionaryCacheText
+    
+    Function isWhiteSpace String sChar Returns Boolean 
+        If (sChar = " ") Function_Return (True)
+        If (sChar = Character(13)) Function_Return (True)  
+        If (sChar = Character(10)) Function_Return (True)  
+        If (sChar = Character(9)) Function_Return (True)  
+        Function_Return (False)
+    End_Function
+    
+    Function isJSONDictionary String sInp Returns Boolean 
+        Integer iPos 
+        String sChar 
+        For iPos from 1 to (Length(sInp))
+            Move (Mid(sInp,1,iPos)) to sChar 
+            If (not(isWhiteSpace(Self,sChar))) Function_Return (sChar = "{")
+        Loop
+        Function_Return (False)
+    End_Function
+    
+    Function isJSON String sInp Returns Boolean 
+        Integer iPos 
+        String sChar 
+        For iPos from 1 to (Length(sInp))
+            Move (Mid(sInp,1,iPos)) to sChar 
+            If (not(isWhiteSpace(Self,sChar))) Begin 
+                If (sChar = "[") Function_Return (True)
+                If (sChar = "{") Function_Return (True)
+                If (sChar = '"') Function_Return (True)
+                Function_Return (False)
+            End
+        Loop
+        Function_Return (False)
+    End_Function
+    
+    Function isJSONArray String sInp Returns Boolean 
+        Integer iPos 
+        String sChar 
+        For iPos from 1 to (Length(sInp))
+            Move (Mid(sInp,1,iPos)) to sChar 
+            If (not(isWhiteSpace(Self,sChar))) Function_Return (sChar = "[")
+        Loop
+        Function_Return (False)
+    End_Function
+
+    Function theTime Returns String 
+        Date dDate 
+        Integer iHrs 
+        Integer iMins 
+        Integer iSecs 
+        Sysdate dDate iHrs iMins iSecs 
+        Showln iHrs ":" iMins ":" iSecs 
+    End_Function
+    
+    // { 
+    Function SplitJSONDictionary String sInp Returns tJSONDictionary[]
+        tJSONDictionary[] aDictionary
+        tJSONDictionary jsonItem
+        Integer iPos 
+        Integer iMax 
+        String sToken  
+        Boolean isEscape
+        Integer iType 
+        String sState
+        String sProperty
+        String sValue 
+        Integer iQuoteLevel
+        Boolean isInsideQuote
+        String sUnicode
+        Integer iUnicode
+
+        If (sInp = (psDictionaryCacheText(Self))) Begin 
+            Function_Return (pCacheDictionary(Self))
+        End
+
+        Move "outside" to sState 
+        Move (False) to isInsideQuote
+        
+        Move "" to sProperty
+        Move (False) to isEscape 
+        Move (Length(sInp)) to iMax 
+        
+
+        Char[] myCharArray
+        Address pStr
+        Move (ResizeArray(myCharArray,iMax+5)) to myCharArray
+        Move (AddressOf(myCharArray)) to pStr
+        Move sInp to pStr
+
+        For iPos from 0 to (iMax-1)
+            //Move (Mid(sInp,1,iPos)) to sToken
+            Move (character(myCharArray[iPos])) to sToken 
+
+            If ((not(isEscape)) and (sToken = '"')) Move (not(isInsideQuote)) to isInsideQuote
+            
+            If (sState = "outside") Begin 
+                Move "" to sProperty
+                If (sToken="{") Move "objectname" to sState
+            End
+            
+            Else If (sState = "objectname") Begin
+                If (isWhiteSpace(Self,sToken)) Begin 
+                End
+                Else If (sToken = '"') Begin 
+                    Move "" to sProperty
+                    Move "quotedobjectname" to sState 
+                End
+                Else If (sToken = ":") Begin 
+                    Move "objectvalue" to sState
+                    Move "" to sValue 
+                End
+                Else Begin 
+                    Append sProperty sToken 
+                End
+            End
+            
+            Else If (sState = "quotedobjectname") Begin 
+                If (sToken = '"') Begin 
+                    Move "objectname" to sState 
+                End
+                Else Begin 
+                   Append sProperty sToken  
+                End
+            End
+            
+            Else If (sState = "objectvalue") Begin 
+                If (isWhiteSpace(Self,sToken)) Begin 
+                    If (isInsideQuote) Append sValue sToken
+                End
+                Else If ((sToken = '"') and (iQuoteLevel = 0)) Begin 
+                    Move "quotedobjectvalue" to sState 
+                    Move 0 to iQuoteLevel
+                End
+                Else If ((sToken = ",") and (iQuoteLevel = 0)) Begin 
+                    Move (trim(sProperty)) to jsonItem.sItem
+                    Move (trim(sValue)) to jsonItem.sValue
+                    Move jsonItem to aDictionary[ (SizeOfArray(aDictionary)) ]
+                    
+                    Move "objectname" to sState 
+                    Move "" to sProperty
+                    Move "" to sValue 
+                End
+                Else If ((sToken = "}") and (iQuoteLevel = 0)) Begin 
+                    Move (trim(sProperty)) to jsonItem.sItem
+                    Move (trim(sValue)) to jsonItem.sValue
+                    Move jsonItem to aDictionary[ (SizeOfArray(aDictionary)) ]
+
+                    Move "outside" to sState 
+                    Move "" to sProperty
+                    Move "" to sValue 
+                End 
+                Else Begin 
+                    If (not(isInsideQuote)) Begin 
+                        If (sToken = "[") Move (iQuoteLevel+1) to iQuoteLevel
+                        If (sToken = "{") Move (iQuoteLevel+1) to iQuoteLevel
+                        If (sToken = "]") Move (iQuoteLevel-1) to iQuoteLevel
+                        If (sToken = "}") Move (iQuoteLevel-1) to iQuoteLevel
+                        If (iQuoteLevel < 0) Move 0 to iQuoteLevel
+                    End
+                    Append sValue sToken 
+                End
+            End
+            
+            Else If (sState = "quotedobjectvalue") Begin 
+                If (isEscape) Begin 
+                    If (sToken = '"') Append sValue '"'
+                    Else If (sToken = '\') Append sValue '\'
+                    Else If (sToken = '/') Append sValue '/'
+                    Else If (sToken = 'f') Append sValue (Character(13))
+                    Else If (sToken = 'n') Append sValue (Character(10)) (Character(13))
+                    Else If (sToken = 'r') Append sValue (Character(10))
+                    Else If (sToken = 't') Append sValue (Character(9))
+                    Else If (sToken = 'u') Begin 
+                        Move (character(myCharArray[iPos+1])) to sUnicode 
+                        Append sUnicode (character(myCharArray[iPos+2]))
+                        Append sUnicode (character(myCharArray[iPos+3]))
+                        Append sUnicode (character(myCharArray[iPos+4]))
+                        Move (Integer("$"+sUnicode)) to iUnicode 
+                        If (iUnicode > 254) Move 254 to iUnicode
+                        Append sValue (Character(iUnicode)) 
+                        Move (iPos+4) to iPos  
+                    End
+                    Move (False) to isEscape
+                End
+                Else Begin 
+                    If (sToken = "\") Move (True) to isEscape
+                    Else If (sToken = '"') Begin 
+                        Move "objectvalue" to sState 
+                    End
+                    Else Begin 
+                        Append sValue sToken 
+                    End
+                End
+            End
+        Loop
+        
+        Set psDictionaryCacheText to sInp 
+        Set pCacheDictionary to aDictionary
+        Function_Return aDictionary
+    End_Function
+    
+    Function SplitJSONArray String sInp Returns String[]
+        String[] ValueArray
+        Integer iPos 
+        Integer iMax 
+        String sToken  
+        Boolean isEscape
+        Integer iType 
+        String sState
+        String sValue 
+        Integer iQuoteLevel
+        Boolean isInsideQuote
+        String sUnicode
+        Integer iUnicode
+        
+        If (sInp = (psArrayCacheText(Self))) Begin 
+            Function_Return (pCacheValueArray(Self))
+        End
+
+        Move "outside" to sState 
+        
+        Move 0 to iQuoteLevel
+        Move "" to sValue
+        Move (False) to isEscape 
+        Move (Length(sInp)) to iMax 
+
+        Char[] myCharArray
+        Address pStr
+        Move (ResizeArray(myCharArray,iMax+1)) to myCharArray
+        Move (AddressOf(myCharArray)) to pStr
+        Move sInp to pStr
+
+        Move "outside" to sState 
+        For iPos from 0 to (iMax-1)
+            Move (character(myCharArray[iPos])) to sToken
+            
+            If ((not(isEscape)) and (sToken = '"')) Move (not(isInsideQuote)) to isInsideQuote
+            
+            If (sState = "outside") Begin 
+                Move "" to sValue
+                If (sToken="[") Move "objectvalue" to sState
+            End
+            
+            Else If (sState = "objectvalue") Begin 
+                If (isWhiteSpace(Self,sToken)) Begin 
+                    If (isInsideQuote) Append sValue sToken
+                End
+                Else If ((sToken = '"') and (iQuoteLevel = 0)) Begin 
+                    Move "quotedobjectvalue" to sState 
+                End
+                Else If ((sToken = ",") and (iQuoteLevel = 0)) Begin 
+                    Move (trim(sValue)) to ValueArray[ (SizeOfArray(ValueArray)) ]
+                    Move "" to sValue
+                    Move "objectvalue" to sState 
+                End
+                Else If ((sToken = "]") and (iQuoteLevel = 0)) Begin 
+                    Move (trim(sValue)) to ValueArray[ (SizeOfArray(ValueArray)) ]
+                    Move "outside" to sState 
+                End 
+                Else Begin 
+                    If (not(isInsideQuote)) Begin
+                        If (sToken = "[") Move (iQuoteLevel+1) to iQuoteLevel
+                        If (sToken = "{") Move (iQuoteLevel+1) to iQuoteLevel
+                        If (sToken = "]") Move (iQuoteLevel-1) to iQuoteLevel
+                        If (sToken = "}") Move (iQuoteLevel-1) to iQuoteLevel
+                        If (iQuoteLevel < 0) Move 0 to iQuoteLevel
+                    End
+                    Append sValue sToken 
+                End
+            End
+            
+            Else If (sState = "quotedobjectvalue") Begin 
+                If (isEscape) Begin 
+                    If (sToken = '"') Append sValue '"'
+                    Else If (sToken = '\') Append sValue '\'
+                    Else If (sToken = '/') Append sValue '/'
+                    Else If (sToken = 'f') Append sValue (Character(13))
+                    Else If (sToken = 'n') Append sValue (Character(10)) (Character(13))
+                    Else If (sToken = 'r') Append sValue (Character(10))
+                    Else If (sToken = 't') Append sValue (Character(9))
+                    Else If (sToken = 'u') Begin 
+                        Move (character(myCharArray[iPos+1])) to sUnicode 
+                        Append sUnicode (character(myCharArray[iPos+2]))
+                        Append sUnicode (character(myCharArray[iPos+3]))
+                        Append sUnicode (character(myCharArray[iPos+4]))
+                        Move (Integer("$"+sUnicode)) to iUnicode 
+                        If (iUnicode > 254) Move 254 to iUnicode
+                        Append sValue (Character(iUnicode)) 
+                        Move (iPos+4) to iPos  
+                    End
+                    Move (False) to isEscape
+                End
+                Else Begin 
+                    If (sToken = "\") Move (True) to isEscape
+                    Else If (sToken = '"') Begin 
+                        Move "objectvalue" to sState 
+                    End
+                    Else Begin 
+                        Append sValue sToken 
+                    End
+                End
+            End
+        Loop
+
+        Set pCacheValueArray to ValueArray
+        Set psArrayCacheText to sInp 
+        Function_Return ValueArray
+    End_Function
+
+    Function JSONValue String sTmp Returns String 
+        String sPos 
+        
+        Move (Trim(sTmp)) to sTmp 
+        If ((left(sTmp,1))='"') Move (Mid(sTmp,(Length(sTmp))-1,2)) to sTmp 
+        If ((right(sTmp,1))='"') Move (Mid(sTmp,(Length(sTmp))-1,1)) to sTmp 
+        Move (Replaces('\"',sTmp,'"')) to sTmp 
+        Move (Replaces('\t',sTmp, (Character(9)) )) to sTmp 
+        Move (Replaces('\r"',sTmp, (Character(10)))) to sTmp 
+        Move (Replaces('\f"',sTmp, (Character(13)))) to sTmp 
+        Move (Replaces('\\"',sTmp, "\")) to sTmp 
+        
+        Function_Return sTmp 
+    End_Function
+    
+    Function DictionaryMatches tJSONDictionary DictItem tJSONDictionary sSearchDict Returns Integer
+        Integer iRetVal
+        String sTest 
+        String sSearchFor 
+        
+        Move (lowercase(DictItem.sItem)) to sTest 
+        Move (Lowercase(sSearchDict.sItem)) to sSearchFor 
+        
+        If (sSearchFor = sTest) Function_Return (EQ)
+        Else Function_Return (NE)
+    End_Function  // MyComparison
+
+    Function DictionaryValue tJSONDictionary[] aDictionary String sSearch Returns String 
+        Integer iPos
+        tJSONDictionary sSearchDict
+        
+        Move sSearch to sSearchDict.sItem
+         
+        Move (SearchArray( sSearchDict, aDictionary, Self, get_DictionaryMatches )) to iPos 
+        If (iPos = -1) Function_Return ""
+        
+        Function_Return aDictionary[iPos].sValue
+    End_Function
+
+End_Object
+
+Class cSelectJSON is a cObject 
+    Procedure Construct_Object
+        Forward Send Construct_Object
+        Property String psData 
+    End_Procedure
+    
+    Function JSONisNumeric String sCode Returns Integer
+        Integer iLength
+        Integer iPos
+        String sTmpChar
+    
+        Move (Replace(".",sCode,"")) to sCode 
+        Move (length(sCode)) to iLength
+        For iPos from 1 to iLength
+            Move (mid(sCode,1,iPos)) to sTmpChar
+            If (pos(sTmpChar,'01234567890')) eq 0 Function_Return (False)
+        Loop
+        Function_Return (True)
+    End_Function
+
+    Function JSONSplitToArray String sVal String sChar Returns String[]
+        String[] astVal
+        String sHold
+        Integer iCount
+        
+        While (Pos(sChar, sVal)>0)
+            // fetch first string
+            Move (Left(sVal, Pos(sChar, sVal)-1)) to sHold
+            // store value in array
+            Move sHold to astVal[iCount]
+            Increment iCount
+            // remove value from string
+            Move (Replace(sHold+sChar, sVal, "")) to sVal
+        Loop
+        // move whatever is last to the end of the array
+        Move sVal to astVal[iCount]
+        Function_Return astVal
+    End_Function // Split
+
+    Function JSONValue String sSearch Returns String 
+        String[] aCrumbs
+        Integer iPos 
+        Integer iMax
+        String sresults 
+        tJSONDictionary[] aDictionary
+        String[] arJSON
+        String sCrumb
+        Integer iArrayPos
+        
+        Get psData to sResults 
+        Move (Replaces("[",sSearch,".[")) to sSearch 
+        Move (Replaces("..",sSearch,".")) to sSearch
+        If ((Left(sSearch,1))=".") Move (Mid(sSearch,(Length(sSearch)),2)) to sSearch
+        
+        Move (JSONSplitToArray(Self,sSearch,".")) to aCrumbs
+        Move (SizeOfArray(aCrumbs)) to iMax
+        For iPos from 0 to (iMax-1) 
+            Move aCrumbs[iPos] to sCrumb
+            
+            If ((sCrumb = "") or (sCrumb=".")) Begin 
+                //nothing
+            End
+            Else If ((Pos("[",sCrumb)) = 1) Begin 
+                Move (Replaces("[",sCrumb,"")) to sCrumb 
+                Move (Replaces("]",sCrumb,"")) to sCrumb 
+                If (JSONisNumeric(Self,sCrumb)) Move sCrumb to iArrayPos
+                
+                Move (SplitJSONArray(oJSON,sresults)) to arJSON
+                If (iArrayPos >= (sizeOfArray(arJSON))) Function_Return ""
+                Else Move arJSON[iArraypos] to sResults
+            End
+            Else Begin 
+                Move (SplitJSONDictionary(oJSON,sResults)) to aDictionary
+                Move (DictionaryValue(oJSON,aDictionary,sCrumb)) to sresults 
+            End
+        Loop
+        Function_Return sresults 
+    End_Function
+    
+    Function JSONDictionary String sSearch Returns tJSONDictionary[]
+        String sresults 
+        tJSONDictionary[] aDictionary
+        
+        Move (JSONValue(Self,sSearch)) to sresults 
+        Move (SplitJSONDictionary(oJSON,sResults)) to aDictionary
+        Function_Return aDictionary
+    End_Function
+    
+    Function JSONArray String sSearch Returns String[] 
+        String[] arJSON
+        String sresults
+        
+        Move (JSONValue(Self,sSearch)) to sresults 
+
+        Move (SplitJSONArray(oJSON,sresults)) to arJSON
+        Function_Return arJSON
+    End_Function
+    
+    //set psData of oSelectJSON to sData 
+    //get JSONValue of oSelectJSON "results[0].geometry.location.lat" to nLAT 
+    //get JSONDictionary of oSelectJSON "results[0].geometry.location to dctLocation
+    //get JSONArray of oSelectJSON "results" to aStrings
+    
+End_Class
+
+Object oSelectJSON is a cSelectJSON 
+End_Object