I can't say I have experience with it yet but NTK has JSON Parsing methods that look quite good.
As another option here is a library I converted from a C# parser. I am
not actually using this library however so be cautious. I will probably
be using the NTK methods going forward. Of particular note is that
return values from various functions could be of different types so be
carefull.
If you choose to use this library, import as normal and call it such as
:
C_boolean($Success)
$jsonCollection := JSON_Decode($JsonString; $Success)
Note that if the decoding does not work then the jsonCollection is
probably not a collection.
library "a4d.jsonParser"
// Converted from C# parser found at :
//
http://techblog.procurios.nl/k/news/view/14605/14863/How-do-I-write-my-o
wn-parser-for-JSON.html
define(TOKEN_NONE; 0)
define(TOKEN_CURLY_OPEN; 1)
define(TOKEN_CURLY_CLOSE; 2)
define(TOKEN_SQUARED_OPEN; 3)
define(TOKEN_SQUARED_CLOSE; 4)
define(TOKEN_COLON; 5)
define(TOKEN_COMMA; 6)
define(TOKEN_STRING; 7)
define(TOKEN_NUMBER; 8)
define(TOKEN_TRUE; 9)
define(TOKEN_FALSE; 10)
define(TOKEN_NULL; 11)
define(DEBUGISON; false)
method "TokenName" ($token)
case of
: ($token = TOKEN_NONE)
$Name := "TOKEN_NONE"
: ($token = TOKEN_CURLY_OPEN)
$Name := "TOKEN_CURLY_OPEN"
: ($token = TOKEN_CURLY_CLOSE)
$Name := "TOKEN_CURLY_CLOSE"
: ($token = TOKEN_SQUARED_OPEN)
$Name := "TOKEN_SQUARED_OPEN"
: ($token = TOKEN_SQUARED_CLOSE)
$Name := "TOKEN_SQUARED_CLOSE"
: ($token = TOKEN_COLON)
$Name := "TOKEN_COLON"
: ($token = TOKEN_COMMA)
$Name := "TOKEN_COMMA"
: ($token = TOKEN_STRING)
$Name := "TOKEN_STRING"
: ($token = TOKEN_NUMBER)
$Name := "TOKEN_NUMBER"
: ($token = TOKEN_TRUE)
$Name := "TOKEN_TRUE"
: ($token = TOKEN_FALSE)
$Name := "TOKEN_FALSE"
: ($token = TOKEN_NULL)
$Name := "TOKEN_NULL"
end case
return ($Name)
end method
method "WriteDebug" ($DebugLine)
if (DEBUGISON)
array text($callchain; 0)
get call chain($callchain)
c_text($logmess)
$logmess := ""
for ($i;size of array($callchain)-2;2;-1)
if ($i > 2)
$logmess += replace
string($callchain{$i};"global.";"")+"->"
else
$logmess += replace
string($callchain{$i};"global.";"")+":"
end if
end for
writebr($logmess+$DebugLine)
log message($logmess+$debugline)
end if
end method
// Parses json string into a collection
method "JSON_Decode" ($json; &$Success)
//c_longint($c)
//$c := 0 // should be a new collection when done
$Success := true
if ($json # "")
c_longint($idx)
$idx := 1 // starting position of
parsing - this is the global location in the parsing of the string
$c := ParseValue($json; $idx; $Success)
end if
return ($c)
end method
method "ParseObject" ($json; &$idx; &$Success)
c_boolean($done)
$done := false
NextToken($json; $idx)
c_longint($token; $c)
$c := new collection
c_text($name)
c_boolean($CallSuccess)
$CallSuccess:=false
while(not($done))
$token := LookAhead($json; $idx)
WriteDebug("Token found : "+TokenName($token))
case of
: ($token = TOKEN_NONE)
writedebug("Failed 0")
$Success := false
$done := true
$c := 0 // return
null collection
: ($token = TOKEN_COMMA)
//writedebug("TOKEN comma
found")
NextToken($json; $idx) // skip
the comma
: ($token = TOKEN_CURLY_CLOSE)
NextToken($json; $idx)
$done := true
else
// Get Name
$name := ParseString($json;
$idx; $Success)
if ($Success)
writedebug("Name =
"+$name+ " json next 20 chars = "+substring($json; $idx; 20))
$token :=
NextToken($json; $idx)
if ($token =
TOKEN_COLON)
//writedebug("Token colon found : Check value")
$cvalue :=
ParseValue($json; $idx; $Success)
writedebug("Type
of cvalue = "+type($cvalue))
if ($Success)
$c{$name} := $cvalue
else
$c
:= 0
$Done
:= true
end if
else
$c := 0
$Done := true
writedebug("Failed 1")
$Success:= false
end if
else
$c := 0
$Done := true
$Success:= false
writedebug("Failed 2")
end if
end case
end while
writedebug("DONE")
return ($c)
end method
method "ParseArray" ($json; &$idx; &$Success)
c_longint($arraylist) // collection
$arraylist := new collection
$Success := true
c_longint($token; $arrayLocation)
$arrayLocation := 1
writedebug("get next token")
NextToken($json; $idx)
c_boolean($done)
$done := false
while(not($done))
$token := LookAhead($json; $idx)
case of
: ($token = TOKEN_NONE)
//writedebug("
$Success := false
$done := true
$arraylist := 0 // kill
collection
: ($token = TOKEN_COMMA)
NextToken($json; $idx)
: ($token = TOKEN_SQUARED_CLOSE)
NextToken($json; $idx)
$done := true
else
$thevalue := ParseValue($json;
$idx; $Success)
if ($Success)
$arraylist{string($arrayLocation)} := $thevalue
$arrayLocation++
else
$done := true
end if
end case
end while
return ($arraylist)
end method
method "ParseValue" ($json; &$idx; &$Success)
//writedebug("calling look ahead for token")
$Success := true
c_longint($token)
$token := LookAhead($json; $idx)
WriteDebug("Token found : "+TokenName($token))
case of
: ($token = TOKEN_STRING)
return (ParseString($json; $idx;
$Success))
: ($token = TOKEN_NUMBER)
return (ParseNumber($json; $idx;
$Success))
: ($token = TOKEN_CURLY_OPEN)
return (ParseObject($json; $idx;
$Success))
: ($token = TOKEN_SQUARED_OPEN)
return (ParseArray($json; $idx;
$Success))
: ($token = TOKEN_TRUE)
NextToken($json; $idx)
return (true)
: ($token = TOKEN_FALSE)
NextToken($json; $idx)
return (false)
: ($token = TOKEN_NULL)
//writedebug("token null found : idx =
"+$idx)
NextToken($json; $idx)
//writedebug("token null found : idx
after next token = "+$idx)
return (0) // success is still true
: ($token = TOKEN_NONE)
$Success := false
else
$Success := false
end case
return (0)
end method
method "ParseString" ($json; &$idx; &$Success)
c_text($s)
$s := ""
EatWhiteSpace($json; $idx)
c_boolean($StartedWithQuote)
$StartedWithQuote := false
c_text($c)
$c := $json[[$idx]]
if ($c = '"')
$idx++ // skip the opening quote
$StartedWithQuote := true
end if
c_boolean($complete)
$complete := false
while(not($complete))
if ($idx > length($json))
break
end if
$c := $json[[$idx]]
// writedebug("ParseString: CheckChar = "+$c)
$idx++
case of
: ($c = '"')
$complete := true
: ($c = '\\')
if ($idx = length($json))
break
end if
$c = $json[[$idx]]
$idx++
case of
: ($c = '"')
$s += '"'
: ($c = '\\')
$s += '\\'
: ($c = '/')
$s += '/'
: ($c = 'b')
$s += '\b'
: ($c = 'f')
$s += '\f'
: ($c = 'n')
$s += '\n'
: ($c = 'r')
$s += '\r'
: ($c = 't')
$s += '\t'
: ($c = 'u')
c_longint($remaininglength)
$remaininglength
= length($json) - $idx + 1;
if
($remaininglength >= 4)
// NOT IMPLEMENTED
// skip
4 chars
$idx +=
4;
else
break //
error - if it is a unicode value the remaining length needs to be >= 4
end if
end case
: ($c = ',')
if ($StartedWithQuote)
$s += $c
else
$complete := true
end if
else
$s += $c
end case
end while
if (not($complete))
writedebug("Failed : '"+$s+"'")
$Success := false;
return "";
end if
writedebug("String Found '"+$s + "' Current
location character = "+$json[[$idx]])
return ($s)
end method
method "ParseNumber" ($json; &$idx; &$Success)
EatWhiteSpace($json; $idx)
c_longint($lastIndex; $charLength)
//writedebug("character at start =
"+substring($json;$idx;10))
$lastIndex := GetLastIndexOfNumber($json; $idx)
$charLength := ($lastIndex - $idx)
c_real($number)
$number := num(substring($json; $idx; $charLength))
$idx := $lastIndex
writedebug("Number is : "+$number)
$Success := true
return ($number)
end method
method "GetLastIndexOfNumber" ($json; $idx)
c_longint($lastIndex)
$lastIndex := $idx
c_boolean($done)
if ($idx <= length($json))
$done := false
repeat
// look for , or ]
if (($json[[$lastIndex]] = ",") |
($json[[$lastIndex]] = "]") | ($json[[$lastIndex]]= "}") |
($json[[$lastIndex]] = " ")) // should cause it to stop on a comma or ]
$done := true
end if
if ($done = false)
$lastIndex++
end if
if ($lastIndex > length($json))
$done := true
exit // bail completely out of
running.
end if
until ($done)
end if
return ($lastIndex)
end method
method "EatWhiteSpace" ($json; &$idx)
$done := false
if ($idx <= length($json))
repeat
if (($json[[$idx]] = " ") |
($json[[$idx]] = "\r") | ($json[[$idx]] = "\n") | ($json[[$idx]] =
"\t"))
if ($idx > 19)
//writedebug("1 IDX =
"+$idx+ " - "+string(ascii($json[[$idx]])))
end if
$idx++
else
$done := true
end if
if ($idx > length($json))
//writedebug("$idx > length of
json string")
$done := true
end if
until ($done)
end if
end method
method "LookAhead" ($json; $idx)
return (NextToken($json; $idx))
end method
method "NextToken" ($json; &$idx)
EatWhiteSpace($json; $idx)
if ($idx > length($json))
return (TOKEN_NONE)
end if
c_text($c)
$c := $json[[$idx]]
// writedebug("NextToken: Starting Character = "+$c)
$idx++
case of
: ($c = '{')
return (TOKEN_CURLY_OPEN)
: ($c = '}')
return (TOKEN_CURLY_CLOSE)
: ($c = '[')
return (TOKEN_SQUARED_OPEN)
: ($c = ']')
return (TOKEN_SQUARED_CLOSE)
: ($c = ',')
return (TOKEN_COMMA)
: ($c = '"')
return (TOKEN_STRING)
: (($c = '0') | ($c = '1') | ($c = '2') | ($c =
'3') | ($c = '4') | ($c = '5') |($c = '6') |($c = '7') | ($c = '8') |
($c = '9') | ($c = '-'))
return (TOKEN_NUMBER)
: ($c = ':')
//writedebug("NextToken: Return Token
Colon")
return (TOKEN_COLON)
end case
$idx--
c_longint($remaininglength)
$remaininglength := length($json) - $idx + 1
if ($remaininglength >= 5)
if (substring($json; $idx; 5) = "false")
$idx += 5
return (TOKEN_FALSE)
end if
if (substring($json; $idx; 4) = "true")
$idx += 4
return (TOKEN_TRUE)
end if
if (substring($json; $idx; 4) = "null")
writedebug("TOKEN NULL FOUND : Character
at index = "+$json[[$idx]])
$idx += 4
return (TOKEN_NULL)
end if
end if
return (TOKEN_NONE)
end method
end library
-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of Michael
Check
Sent: Thursday, August 18, 2011 11:58 AM
To: [email protected]
Subject: [Active4d-dev] Options for json read into 4D
Hi all
Wondering what the current consensus is for the most effective way to
get json data into 4D, via A4D. A4D json lib is a great one way lib,
but we need to send data back and forth between both Rails apps and Ext.
We don't have a need for complex nesting structures, but a basic 1 level
nesting would be nice.
I know Steve Alex had some A4D scripts, and Pelican Engineering has a
JSON component that I was thinking about using to build an A4D lib (I
don't know if the lib is really necessary).
But perhaps I am missing something? Any experience with other methods?
Thanks,
Michael Check
_______________________________________________
Active4D-dev mailing list
[email protected]
http://mailman.aparajitaworld.com/mailman/listinfo/active4d-dev
Archives: http://mailman.aparajitaworld.com/archive/active4d-dev/
-----Original Message-----
From: [email protected]
[mailto:[email protected]] On Behalf Of Michael
Check
Sent: Thursday, August 18, 2011 11:58 AM
To: [email protected]
Subject: [Active4d-dev] Options for json read into 4D
Hi all
Wondering what the current consensus is for the most effective way to
get json data into 4D, via A4D. A4D json lib is a great one way lib,
but we need to send data back and forth between both Rails apps and Ext.
We don't have a need for complex nesting structures, but a basic 1 level
nesting would be nice.
I know Steve Alex had some A4D scripts, and Pelican Engineering has a
JSON component that I was thinking about using to build an A4D lib (I
don't know if the lib is really necessary).
But perhaps I am missing something? Any experience with other methods?
Thanks,
Michael Check
_______________________________________________
Active4D-dev mailing list
[email protected]
http://mailman.aparajitaworld.com/mailman/listinfo/active4d-dev
Archives: http://mailman.aparajitaworld.com/archive/active4d-dev/
_______________________________________________
Active4D-dev mailing list
[email protected]
http://mailman.aparajitaworld.com/mailman/listinfo/active4d-dev
Archives: http://mailman.aparajitaworld.com/archive/active4d-dev/
