Created
January 2, 2011 18:10
-
-
Save salex/762698 to your computer and use it in GitHub Desktop.
A JSON Parse Routine for Active4D with some limitations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<% | |
/********************************************************************************** | |
jsonParseSimple | |
In => $json -> Text in JavaScript Object Notation(JSON) | |
Out => The JSON text parsed to an Active4D collection with some limitations. | |
Active4D cannot do everything that you can in JSON (JavaScript, Ruby, PHP etc). | |
You cannot have an array of mixed types as you can in other languages. | |
This was written for 4D 2004 so there is the 32K text limit on $json | |
The JSON must be enclosed in an object {} or array [] notation | |
It will probably do 100% of what you'd like it to do if you control boths sides (create and parse JSON). It will convert | |
just about any sane JSON I've found at a web service. It will convert anything created with the a4d.json libary. | |
Dates use the "Jan 2, 2011" format as does the a4d.json libary | |
Objects are converted to collection with calls to execute "new collection" | |
Arrays are restricted to text, longint, and real arrays. | |
If a longint array is an array of collections, it will create those collections. | |
This parse process is in five steps. | |
A regex is used to convert dates | |
The JSON is parsed by each character and certain characters (",:\n\r) are changed to high ASCII values or removed | |
A regex replace is set up to change the JSON object notation to Active4D notation | |
The high ASCII characters are returned to their original value | |
The result is executed, which productes the collection. | |
**********************************************************************************/ | |
method "jsonParseSimple"($json) | |
// First convert any dates in IETF format to 4d date | |
$re1 := "~\"?(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)( \\d\\d*, \d{4})\"~" | |
$rp1 := "newDate(\"\1\2\")" | |
regex replace($re1; $json; $rp1; $json) | |
$json := trim($json) | |
if ($json[[1]] = "[") // if json is just an array, wrap in in an object | |
$json := '{"array":$json}' | |
end if | |
//Next, hide commas, colons, apostrophe between quotes | |
$inQuote := false | |
for each ($json; $char; $index) | |
case of | |
:($char = '"') | |
$inQuote := not($inQuote) | |
:(($char = ",") & $inQuote) | |
$json[[$index]] := char(254) | |
:(($char = ":") & $inQuote) | |
$json[[$index]] := char(253) | |
:(($char = "'") & $inQuote) | |
$json[[$index]] := char(252) | |
:(($char = "\n") & not($inQuote)) | |
$json[[$index]] := " " | |
:(($char = "\r") & not($inQuote)) | |
$json[[$index]] := " " | |
:(($char = "\n") & ($inQuote)) | |
$json[[$index]] := char(251) | |
:(($char = "\r") & ($inQuote)) | |
$json[[$index]] := char(251) | |
end case | |
end for each | |
//Now convert objects | |
array text($pattern;0) // regex pattern array | |
array text($replace;0) // reqex replace array | |
// set the reqex array - first the patterns to match | |
$pattern{} := "|:\\s*{|" // object => convert :{ to ;new collection( | |
$pattern{} := "|\\[\\]|" // replace empty array with empty text array -> a call to emptyArray | |
$pattern{} := "|:\\s*\\[|" // text, real, or longint array -> a call to newArray(''' JSON ARRAY ''') | |
$pattern{} := "|\\]|" // end array => convert ] to ) | |
$pattern{} := "|}|" // end object => convert } to ) | |
$pattern{} := "|[:,]|" // replace comma and colon with semi-colon | |
$pattern{} := "|{|" // replace begining object with new collection() | |
$pattern{} := "|new collection\\(\\)|" // replace empty collection convert new collection() with new collection | |
//set the replacement array | |
$replace{} := ";new collection(" // ojects that have a key | |
$replace{} := "emptyArray" // [] | |
$replace{} := ";newArray( ''' " // [..,..,..] | |
$replace{} := " ''')" | |
$replace{} := ")" | |
$replace{} := ";" | |
$replace{} := "new collection(" // collections without a key (an array of collections) | |
$replace{} := "new collection" | |
regex replace($pattern; $json; $replace; $results) // do the replacements | |
//put commas, colon, apos back | |
$results := replace string($results;char(254);",") | |
$results := replace string($results;char(253);":") | |
$results := replace string($results;char(252);"'") | |
$results := replace string($results;char(251);"\\n") | |
// crate the collection from the parsed $results - make Active4D work | |
$collection := execute("return ("+ $results+ ")") | |
//writebr('<textarea>$results</textarea>') | |
//$collection := new collection | |
return($collection) | |
end method | |
/********************************************************************************** | |
emptyArray | |
The response to finding and empty array [] in a JSON object is to | |
return an empty text array | |
**********************************************************************************/ | |
method "emptyArray" | |
array text($result;0) | |
return($result) | |
end method | |
/********************************************************************************** | |
newArray | |
$inList -> Text The JSON array os enclosed in a ''' ''' herdoc string. | |
JSON comma delimiters for the array had been changed to semi-colons at this point. | |
Return either a text array, a longint array, an array of collections, or a real array based in contents. | |
A parenthesis will assume a text array | |
A decimal (.) will assume a real array | |
An array of new collection(...) will create an array of collections (longint) after creating the collections | |
If none of the above, it assumes an array of longint. | |
**********************************************************************************/ | |
method "newArray"($inList) | |
$inList := trim($inList) | |
$isNC := $inList = "new collection@" | |
// Handle an array of collections separately - just deal with top level if nested collection | |
if ($isNC) | |
$level := 0 | |
for each ($inList; $char; $index) | |
case of | |
:($char = "(") | |
$level++ | |
:(($char = ")") ) | |
$level-- | |
:(($char = ";") & ($level = 0)) | |
$inList[[$index]] := "|" | |
end case | |
end for each | |
$cnt := split string($inList;"|";$chunks) | |
array longint($result;size of array($chunks)) | |
for each ($chunks; $value; $index) | |
$ncoll := trim($value) | |
$result{$index} := execute("return ("+ $ncoll+ ")") // execute the new collection text | |
end for each | |
return($result) | |
end if | |
$isReal := "." ~ $inList | |
$isText := '"' ~ $inList | |
$count := split string($inList;";";$chunks) | |
case of | |
:($isText) | |
array text($result;$count) | |
for each ($chunks; $value; $index) | |
$result{$index} := trim(replace string($value;'"';'')) | |
end for each | |
:($isReal) | |
array real($result;$count) | |
for each ($chunks; $value; $index) | |
$result{$index} := num($value) | |
end for each | |
else | |
array longint($result;$count) | |
for each ($chunks; $value; $index) | |
$result{$index} := num($value) | |
end for each | |
end case | |
return($result) | |
end method | |
/********************************************************************************** | |
null | |
The response to finding and Null word in a JSON object is to | |
return a nil pointer ( or could return char(0)) | |
**********************************************************************************/ | |
method "null" | |
return(nil pointer) | |
end method | |
/********************************************************************************** | |
newDate | |
The response to finding and date in a JSON object that is a string formatted | |
in the "Jan 2, 2011" format is to replace it with a 4D date | |
**********************************************************************************/ | |
method "newDate"($date) | |
// replace date in Jan 2, 2011 with 4D date | |
array string(3; $months; *; "Jan"; "Feb"; "Mar"; "Apr"; "May"; "Jun"; "Jul"; "Aug"; "Sep"; "Oct"; "Nov"; "Dec") | |
$date := replace string($date;",";"") | |
$cnt := split string($date;" ";$chunks) | |
$tmp := string(find in array($months;$chunks{1}))+'/$chunks{2}/$chunks{3}' | |
return(date($tmp)) | |
end method | |
$json := """ | |
{ | |
"test-null":null, | |
"test-empty-array": [], | |
"test-empty-collection": {}, | |
"test_true":true, | |
"test_false":false, | |
"test_reala":[3.34,43.5,445.2232], | |
"test_integera":[3,5,66,77,88], | |
"test_texta":["3uj","wd","wm","ib77","iu88"], | |
"jobstageid":1852, | |
"selected": | |
[ | |
{ | |
"citizen": | |
{ | |
"citizen.phone1":"5552149891", | |
"citizen.phone2":"5554799657", | |
"citizen.Address":"51 Lefevere", | |
"citizen.City":"Somewhere", | |
"citizen.state":"AL", | |
"citizen.zip":"01010", | |
"citizen.firstName":"Aladrienne", | |
"citizen.lastName":"Odom", | |
"citizen.mi":"C", | |
"citizen.emailAddress":"[email protected]", | |
"citizen.birthMMDD":"1209", | |
"action":"update", | |
"id":153517 | |
}, | |
"cs_ad": | |
{ | |
"citizen_stage.jobstageid":1852, | |
"citizen_stage.score":"90.7761037140855", | |
"application_data.answers":"g0102g0202g0302g0401g0501g0601g0701g0801g0901g1001g1101g1201g1301e0105e0110", | |
"applicant_id":279 | |
} | |
}, | |
{ | |
"citizen": | |
{ | |
"citizen.phone1":"5552357646", | |
"citizen.phone2":"5552850789", | |
"citizen.Address":"4612 Meridian Street", | |
"citizen.City":"Somewhere", | |
"citizen.state":"MS", | |
"citizen.zip":"01010", | |
"citizen.firstName":"Farrah", | |
"citizen.lastName":"Warren", | |
"citizen.mi":"D", | |
"citizen.emailAddress":"[email protected]", | |
"citizen.birthMMDD":"0828", | |
"action":"update", | |
"id":153843 | |
}, | |
"cs_ad": | |
{ | |
"citizen_stage.jobstageid":1852, | |
"citizen_stage.score":"90.78486334968466", | |
"application_data.answers":"g0102g0202g0301g0401g0501g0601g0701g0801g0901g1001g1101g1201g1301e0105", | |
"applicant_id":417 | |
} | |
}, | |
{ | |
"citizen": | |
{ | |
"citizen.phone1":"5552325995", | |
"citizen.phone2":"5554318634", | |
"citizen.Address":"6527 Old Shell Rd. #64", | |
"citizen.City":"Somewhere", | |
"citizen.state":"AL", | |
"citizen.zip":"01010", | |
"citizen.firstName":"Ballery", | |
"citizen.lastName":"Johnson", | |
"citizen.mi":"", | |
"citizen.emailAddress":"[email protected]", | |
"citizen.birthMMDD":"1220", | |
"action":"update", | |
"id":154260 | |
}, | |
"cs_ad": | |
{ | |
"citizen_stage.jobstageid":1852, | |
"citizen_stage.score":"90.7761037140855", | |
"application_data.answers":"g0102g0202g0301g0402g0501g0601g0701g0801g0901g1001g1101g1201g1301e0105e0111", | |
"applicant_id":562 | |
} | |
} | |
] | |
} """ | |
$c := global.jsonParseSimple($json) | |
a4d.debug.dump collection($c; "test";true) | |
// an array of collections will not dump, but they are collections. | |
for each ($c{"selected"}; $citizen; $index) | |
a4d.debug.dump collection($citizen) | |
end for each | |
%> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment