====== RTI_RJSON Function ======
==== Description ====
The RTI_RJSON function allows you to evaluate a JSON (JavaScript Object Notation) expression. After passing in a JSON expression, you can invoke the function or evaluate the expression, and retrieve results.
RTI_RJSON uses the open source rapidJSON library.
Please include the RTI_RJSON_EQUATES insert in your stored procedures.
==== Syntax ====
//rslt// = **RTI_RJSON**(//method// [, //param1// [, //param2// [, //param3// [, //param4// [, //param5//]]]]])
==== Parameters ====
The function has the following available methods and parameters:
^method^Description^Parameters^Return Value^
|RJSON_MTD_PARSE$|Creates an RJSON object from a JSON expression **NOTE** The handle should be deleted via RJSON_MTD_DELETE$ after use|Param1: the JSON expression|the handle to use for subsequent RTI_RJSON calls if successful, or 0 if unsuccessful|
|RJSON_MTD_DELETE$|Deletes the JSON object|Param1: the variable that contains the previously-created JSON object to delete|"1" if the handle was deleted successfully, or "0" otherwise|
|RJSON_MTD_GETITEM$|Returns a handle to the specified value|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired child item|the handle to the specified item|
|RJSON_MTD_GETITEMTYPE$|Returns an integer specifying the type of item|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired child item|the type of the specified item|
|RJSON_MTD_GETITEMCOUNT$|Returns the number of elements (for an array) or members (for an object)|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired child item|the number of elements(if the specified item is an array) or the number of members (if the specified item is an object)|
|RJSON_MTD_GETITEMVALUE$|Returns the value of the specified item|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired child item|the specified variable’s value ("stringified" as quoted JSON if the object is an array or object type), or an empty string if the item is invalid|
|RJSON_MTD_GETOBJECTMEMBERS$|Returns a dynamic array of all member names of the specified object|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) the path to the desired child item\\ \\ Param3: (optional) delimiter to use (default is @FM)|delimited list of all member names of the specified object|
|RJSON_MTD_GETARRAYELEMENTS|Returns a dynamic array of all element handles for a specified array item|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired child item\\ \\ Param3: (optional) delimiter to use (default is @FM)|a dynamic array of all element handles for the specified array item|
|RJSON_MTD_HASMEMBER|Returns true if the specified item has a member with the specified name|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired child item\\ \\ Param3: Member name to look for|"1" if the specified item contains a member with the specified name, "0" otherwise|
|RJSON_MTD_HASELEMENT|Returns true if the specified item has an element with the specified index|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired child item\\ \\ Param3: 1-based element index|"1" if the specified item has an element with the specified index, "0" otherwise|
|RJSON_MTD_CREATEITEM$|Creates a new JSON item of the specified type and returns a handle to it. **NOTE** The handle must be deleted via RJSON_MTD_DELETE$ after use|Param1: the type of variable to create. Valid types include RJSON_TYPE_OBJECT$, RJSON_TYPE_NUMBER$, RJSON_TYPE_STRING$, RJSON_TYPE_BOOL, and RJSON_TYPE_ARRAY$\\ \\ Param2: the initial value of the created variable\\ \\ Param3: delimiter to use if passing in RJSON_TYPE_ARRAY$ elements|the evaluated variable object|
|RJSON_MTD_SETITEMMEMBER$|Sets an item as a "child" member item of a specified "parent"|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired parent element\\ \\ Param3: name of the member to set\\ \\ Param4: handle to the "child" JSON item|"1" if the member was set correctly, or "0" otherwise|
|RJSON_MTD_SETITEMELEMENT$|Sets an item as an element of a JSON array at the specified index|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired parent element\\ \\ Param3: 0-based index of the element to set\\ \\ Param4: handle to the "child" JSON item|"1" if the member was set correctly, or "0" otherwise|
|RJSON_MTD_SETITEMVALUE$|Sets the value of the specified item|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the "parent" item whose value should be set\\ \\ Param3: (optional) the value to which the variable should be set\\ \\ Param4: (optional) type of value to set - 1 (NULL), 2 (BOOL), 3 (NUMBER), or 6 (STRING) (default is 6)|"1" if successful, or "0" otherwise|
|RJSON_MTD_SETITEMARRAY$|Creates and sets an array for the specified item|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the "parent" item whose value should be set\\ \\ Param3: the member name to set (if the specified item is an object) or the index to set the new array at\\ \\ Param4: Dynamic array of values to set\\ \\ Param5: (optional) delimiter used in dynamic array (default is @FM)|"1" if successful, or "0" otherwise|
|RJSON_MTD_APPENDITEM$|Appends an item to an existing array item|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired parent element\\ \\ Param3: handle to the "child" JSON item to append|"1" if successful, "0" otherwise|
|RJSON_MTD_APPENDVALUE$|Appends a value to the specified array|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired parent element\\ \\ Param3: (optional) new value to append\\ \\ Param4: (optional) type of value to append\\ **NOTE** the value must be of type 1 (NULL), 2 (BOOL), 3 (NUMBER), or 6 (STRING)|"1" if successful, "0" otherwise|
|RJSON_MTD_APPENDARRAY$|Creates an array item and appends it to an owner array item|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired parent element\\ \\ Param3: dynamic array of values to set\\ \\ Param4: (optional) delimiter to use when parsing dynamic array (default is @FM)| "1" if successful, "0" otherwise|
|RJSON_MTD_REMOVEITEM$|Removes the specified member from an object item, or the specified element from an array item|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired parent element\\ \\ Param3: the member name to remove (if the specified element is an object) or the index to remove|"1" if the item was successfully removed, "0" otherwise|
|RJSON_MTD_REMOVEALL$|Removes all members from an object item, or all elements from an array item|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired parent element|"1" if the item was successfully removed, "0" otherwise|
|RJSON_MTD_STRINGIFY$|Serializes the specified JSON object into a string format|Param1: the variable that contains the previously-created JSON object\\ \\ Param2: (optional) path to the desired child item|the string representation of the JSON object|
|RJSON_MTD_VALIDATE$|Validates the passed JSON document text against a JSON schema|Param1: JSON text to validate\\ \\ Param2: JSON schema to validate against|"0" if no error, or an error number less than 0|
==== Example ====
Example 1:
compile function test_rjson( void )
$insert rti_rJSON_Equates
$insert rti_SSP_Equates
$insert logical
json = '{'
json := '"results" : ['
json := '{'
json := '"business_status" : ' : quote( "OPERATIONAL" ) : ","
json := '"formatted_address" : ' : quote( "1 Park W Blvd #130, Akron, OH 44320, United States" ) : ","
json := '"geometry" : ' : quote( "2D" )
json := '},'
json := '{'
json := '"business_status" : ' : quote( "DEAD" ) : ","
json := '"formatted_address" : ' : quote( "11 The Yellow Brick Road, Oz" ) : ","
json := '"geometry" : ' : quote( "weird" )
json := '}'
json := ']'
json := '}'
objDoc = rti_rJSON( RJSON_MTD_PARSE$, json ); goSub checkErr
if objDoc then
resultsCount = rti_rJSON( RJSON_MTD_GETITEMCOUNT$, objDoc, "results" ); goSub checkErr
call rti_rJSON( RJSON_MTD_DELETE$, objDoc ); goSub checkErr
end else
goSub checkErr
end
return ""
checkErr:
if get_Status( errText ) then
call set_Status( SETSTAT_OK$ )
debug
end
return
Example 2:
Function Google_Maps_Address_latLng_Example(address)
/*
** Example of calling google maps api to get lat_lng of an address
**
** 03-17-25 rjc Created
*/
#pragma format_indent_comments
$insert logical
$insert rti_RJSON_Equates
$Insert rti_Text_Equates
Declare Function ole_getwebpage, rti_get_cfg
retval = null$
lats = null$
lngs = null$
If Assigned(address) Else address = null$
If address == null$ Then
Return null$
End
apikey = rti_get_cfg("GOOGLE_MAPS_API_KEY")
* Constuct the URL - use URLENCODE to escape special characters
geocode_url = "https://maps.googleapis.com/maps/api/geocode/json"
geocode_url := "?address=":Iconv(address, '[URL_FORMAT]')
geocode_url := "&key=":apikey
* CAll Google's API, get a JSON response
http_method = "GET"
payload = null$;headers = null$;credentials = null$;timeoutInfo = null$;responseFile = null$
geocode_json = ole_getwebpage( geocode_url, http_method, payload, credentials, headers, timeoutInfo)
* Parse the JSON
hJson = rti_rjson(RJSON_MTD_PARSE$,geocode_json)
*---
* Need to parse out location.lat, location.lng
* This particular google API call returns an array of lat/lng values.
* I want to make a list of the lats and lngs
* Below are two equivalent approaches. Choose one.
*---
***
* Method 1 - Iterate accross the array using the main JSON object
***
* itemcount on the 'results' item, specify a path relative to the main item
itemCount = rti_rjson(RJSON_MTD_GETITEMCOUNT$, hJson, "results")
* We are working with the main hJson object, so spectify full path
* Array index is 0 based, so subtract 1
For i = 1 To itemcount
lats = rti_rjson(RJSON_MTD_GETITEMVALUE$, hJson, "results[" : i - 1 : "].geometry.location.lat")
lngs = rti_rjson(RJSON_MTD_GETITEMVALUE$, hJson, "results[" : i - 1 : "].geometry.location.lng")
Next
*----
* Method 2 - Alternative approach to iterating across the array
* get the handle of the results item, specify a path to relative to that item
*----
hRslt = rti_rjson(RJSON_MTD_GETITEM$, hJson, "results")
* Do we have an array [1,2,3] or object {"one":1,"two":2,"three":3} ?
itemType = rti_rjson(RJSON_MTD_GETITEMTYPE$, hRslt)
* use the appropriate method to get a list of handles for all the children in 'results'
* itemElements will be an fm delimited array of childitem handles
itemElements = ""
If itemType == RJSON_TYPE_ARRAY$ then
itemElements = rti_rjson(RJSON_MTD_GETARRAYELEMENTS$, hRslt)
End Else
itemElements = rti_rjson(RJSON_MTD_GETOBJECTMEMBERS$, hRslt)
End
* Get the length or results. Since handle is for 'results', no need to specify a sub path
* note, could also fieldcount(itemElements)
itemCount = rti_rjson(RJSON_MTD_GETITEMCOUNT$, hRslt)
* Iterate across the child items, get the values
* In this example, hItem is the handle for an element in the array, e.g. results[2], so path is relative to the item, not results[i]
*
For i = 1 To itemCount
* itemElements is a dynamic array of handles
hItem = itemElements
lats = rti_rjson(RJSON_MTD_GETITEMVALUE$, hItem, "geometry.location.lat")
lngs = rti_rjson(RJSON_MTD_GETITEMVALUE$, hItem, "geometry.location.lng")
Next
* Release the memory used by the object JSON object
unused = rti_rjson(RJSON_MTD_DELETE$, hJson)
* Return lat / lng
retval = lats:@vm:lngs
Return retval