Post by Brandon Parker on May 4, 2020 20:41:36 GMT -5
Well, in order to fully support JSON parsing you will need to write a Lexer/Tokenizer and then store the tokens/data into an Abstract Syntax Tree. This is NOT a simple task to implement.
JSON, in my humble opinion, is always a disaster waiting to happen due to incorrectly formatted structure. A good JSON parser would have to handle malformed files correctly and meet all of the specifications for the JSON standard as well.
That being said, here is another example that is WAY more complex. I tested it by grabbing different data from the website, the list of buses, and then drilling down to specific subfields in the example JSON Example 2 (also shown below).
This may not work for every case, but feel free to do some testing ...
There's not much error checking for malformed stuff so I would only test with JSON that is known to be good.
*** Make sure to change the file path for the JSON_Example2_Test.txt file on Option 3 ***
Here is the JSON Example 2 for testing.
{:0)
Brandon Parker
JSON, in my humble opinion, is always a disaster waiting to happen due to incorrectly formatted structure. A good JSON parser would have to handle malformed files correctly and meet all of the specifications for the JSON standard as well.
That being said, here is another example that is WAY more complex. I tested it by grabbing different data from the website, the list of buses, and then drilling down to specific subfields in the example JSON Example 2 (also shown below).
This may not work for every case, but feel free to do some testing ...
There's not much error checking for malformed stuff so I would only test with JSON that is known to be good.
*** Make sure to change the file path for the JSON_Example2_Test.txt file on Option 3 ***
Global False : False = 0
Global True : True = 1
Input "Which case do you want to test (1 - Website, 2 - Buses String, 3 - JSON Example? ";testCase
Select Case testCase
Case 1
symbol$ = "VIAC"
field$ = "previousClose"
URL$ = "https://query1.finance.yahoo.com/v8/finance/chart/" + symbol$ + "?region=US&lang=en-US"
jsonData$ = HTTPGet$(URL$)
Case 2
field$ = "buses"
'{ "buses": [{ "name": "Michigan", "license": "A1" }, { "name": "New York", "license": "A2" }] }
jsonData$ = "{ ";chr$(34);"buses";chr$(34);": [{ ";chr$(34);"name";chr$(34);": ";chr$(34);"Michigan";chr$(34);", ";chr$(34); _
"license";chr$(34);": ";chr$(34);"A1";chr$(34);" }, { ";chr$(34);"name";chr$(34);": ";chr$(34);"New York";chr$(34); _
", ";chr$(34);"license";chr$(34);": ";chr$(34);"A2";chr$(34);" }] }"'HTTPGet$(URL$)
Case 3
'***************************************************
' Change this path to where you save Example 2
'***************************************************
field$ = "maths|q2|answer"
Open "D:\JSON_Example2_Test.txt" For Input As #JSON
If LOF(#JSON) Then
jsonData$ = INPUT$(#JSON, LOF(#JSON))
End If
Close #JSON
End Select
Print getFieldFromJSON$(field$, jsonData$)
End
'_________________________________________________________________________________________________________________________________________________________
'_________________________________________________________________________________________________________________________________________________________
Function getFieldFromJSON$(field$, json$)
'This is complicated replacing, but the PIPE character is the delimiter; we need to remove white-space ... that's what
'we are doing here - flattening the string; you can always add something to be removed by adding to the searchfor$ & replacewith$ fields
json$ = ReplaceString$(1, json$, chr$(13);"|";chr$(10);"|";chr$(9);"|, |: |[ |] |{ |} | ";chr$(34);" | ";chr$(34);"|";chr$(32), _
" | | |,|:|[|]|{|}|";chr$(34);"|";chr$(34);"|", "|", True)
key$ = chr$(34) + Word$(field$, 1, "|") + chr$(34) + ":"
keyPosition = Instr(json$, key$)
If Not(keyPosition) Then getFieldFromJSON$ = "ERROR" : Exit Function
'Let's check for a collection
If (Mid$(json$, (keyPosition + Len(key$)), 1) = "[") Then
keyPosition = (keyPosition + 1)
endContChar$ = "]"
End If
getFieldFromJSON$ = Mid$(json$, (keyPosition + Len(key$)))
fieldSeparator = Instr(field$, "|")
If (fieldSeparator > False) And Not(fieldSeparator = Len(field$)) Then
field$ = Mid$(field$, (fieldSeparator + 1))
'We need this many closed braces for the group
numOpenBrace = CountSubstring(Left$(getFieldFromJSON$, Instr(getFieldFromJSON$, "}")), "{", 1, CountSubstring)
endOfGroup = positionOfChar(getFieldFromJSON$, "}", 1, numOpenBrace)
getFieldFromJSON$ = getFieldFromJSON$(field$, Left$(getFieldFromJSON$, endOfGroup))
Else
If (endContChar$ = "]") Then
getFieldFromJSON$ = UpTo$(Mid$(json$, (keyPosition + Len(key$))), "]")
Else
If Instr(Mid$(json$, (keyPosition + Len(key$))), ",";chr$(34)) Then
getFieldFromJSON$ = UpTo$(Mid$(json$, (keyPosition + Len(key$))), ",";chr$(34))
Else
getFieldFromJSON$ = UpTo$(Mid$(json$, (keyPosition + Len(key$))), "}")
End If
End If
getFieldFromJSON$ = IIf$(str$(Left$(getFieldFromJSON$, 1) = chr$(34));">False", Mid$(getFieldFromJSON$, 2), getFieldFromJSON$)
getFieldFromJSON$ = IIf$(str$(Right$(getFieldFromJSON$, 1) = chr$(34));">False", Left$(getFieldFromJSON$, (Len(getFieldFromJSON$) - 1)), getFieldFromJSON$)
End If
End Function
'_________________________________________________________________________________________________________________________________________________________
'_________________________________________________________________________________________________________________________________________________________
Function ReplaceString$(startpos, ReplaceString$, searchfor$, replacewith$, delim$, conditional)
If Not(conditional) Then Exit Function
'searchfor$/ replacewith$ can now be multiple items, but should be matched pairs
'if not then any remaing replaces will be with a NULL string
searchForMe$ = searchfor$ : replacewithMe$ = replacewith$
If searchfor$ <> " " Then
searchForMe$ = Word$(searchfor$, (myWord + 1), delim$)
replacewithMe$ = Word$(replacewith$, (myWord + 1), delim$)
End If
Do While searchForMe$ <> ""
foundPosition = Instr(ReplaceString$, searchForMe$, startpos)
If foundPosition Then
Do While (foundPosition <> _NULL)
ReplaceString$ = Left$(ReplaceString$, (foundPosition - 1)) + replacewithMe$ + _
Mid$(ReplaceString$, (foundPosition + Len(searchForMe$)))
foundPosition = Instr(ReplaceString$, searchForMe$, (foundPosition + Len(replacewithMe$)))
Loop
End If
myWord = (myWord + 1)
searchForMe$ = Word$(searchfor$, (myWord + 1), delim$)
replacewithMe$ = Word$(replacewith$, (myWord + 1), delim$)
Loop
End Function
'_________________________________________________________________________________________________________________________________________________________
'_________________________________________________________________________________________________________________________________________________________
Function CountSubstring(ByRef string$, substring$, position, CountSubstring)
position = Instr(string$, substring$, position)
If position Then CountSubstring = CountSubstring(string$, substring$, (position + Len(substring$)), (CountSubstring + 1))
End Function
'_________________________________________________________________________________________________________________________________________________________
'_________________________________________________________________________________________________________________________________________________________
Function positionOfChar(ByRef string$, char$, positionOfChar, num)
If Not(num) Then
positionOfChar = (positionOfChar + 1)
Exit Function
End If
positionOfChar = Instr(string$, char$, positionOfChar)
'We need to increase the number of open braces (num) if we encounter more on
'our way to the end of the group
If CountSubstring(Mid$(string$, (positionOfChar + 1)), "{", 1, CountSubstring) Then
num = (num + 1)
End If
positionOfChar = positionOfChar(string$, char$, (positionOfChar + 1), (num - 1))
End Function
'_________________________________________________________________________________________________________________________________________________________
'_________________________________________________________________________________________________________________________________________________________
Function IIf$(condition$, trueAnswer$, falseAnswer$)
IIf$ = falseAnswer$ : If condition$ = "" Then Exit Function
If Val(Eval$(condition$)) Then IIf$ = trueAnswer$
End Function
'_________________________________________________________________________________________________________________________________________________________
'_________________________________________________________________________________________________________________________________________________________
Here is the JSON Example 2 for testing.
{
"quiz": {
"sport": {
"q1": {
"question": "Which one is correct team name in NBA?",
"options": [
"New York Bulls",
"Los Angeles Kings",
"Golden State Warriros",
"Huston Rocket"
],
"answer": "Huston Rocket"
}
},
"maths": {
"q1": {
"question": "5 + 7 = ?",
"options": [
"10",
"11",
"12",
"13"
],
"answer": "12"
},
"q2": {
"question": "12 - 8 = ?",
"options": [
"1",
"2",
"3",
"4"
],
"answer": "4"
}
}
}
}
{:0)
Brandon Parker