Chapter 2—OJSON

The OJSON external component allows you to manipulate JSON based content in your Omnis applications – specifically it can be used to handle content returned by REST based web services. JSON is a text form that allows you to transmit data objects consisting of attribute–value pairs, and is an alternative to XML.

It is used in the Export Library to JSON option in Omnis, which provides a convenient way to store libraries and classes in a version control environment such as GIT. In addition, JSON is used to store various Omnis configuration files, including the main config.json, as well as the theme files.

The JSON component provides two ways to generate and parse JSON objects and documents:

  1. A basic mechanism that simply maps directly between an Omnis list or row and JSON. This uses static methods in the OJSON component.

  2. A more structured mechanism that uses an external component object called JSON in the OJSON external component.

Data Structure and Addressing

JSON maps on to a hierarchical Omnis list or row, with one exception, namely that it allows for mixed types in arrays – Omnis can cater for mixed types in list columns internally, but there is no support in the Omnis language for such a list column. Therefore:

  1. you can map a JSON object to an Omnis row variable, where the column names are the JSON object member names.

  2. you can map a JSON array where all of the members have the same primitive type (or null) to a single column Omnis list.

  3. you can map a JSON array where the members are arrays or objects, or where there is more than one primitive type, to an Omnis row variable with columns named___1, ___2, etc. Note that this restricts such arrays to a dimension of 32000 or less.

Note: Primitive types are string, integer, float and Boolean.

The external component JSON object implemented in OJSON uses a character string called the member id to address an entity in a JSON document (an entity is essentially a node in the JSON document tree, so it can represent a primitive type, null, an array or an object):

  1. The member id of the root of the document is the empty character string.

  2. The member id for other objects is the dot-separated path through the document to the entity e.g.

  1. If the root is an object with members a, b and c, the member ids for the object members are: a b and c

  2. If b is an array with two elements, the member ids of the array elements are b.[0] and b.[1]

  3. If b.[1] is an object with string member c, then c has the member id b.[1].c

Using member ids you can directly address any entity in the JSON document. Note that the empty member id can only be used to address the array or object which the root of the JSON document tree.

JSON Arrays

Omnis allows you to manipulate JSON arrays of objects, mapping them to and from Omnis list variables. There are two static functions in the OJSON external, $objectarraytolist() and $listtoobjectarray(), that work with a single level JSON array, where each array element is an object, and each object has members which are only simple types (integer, number, boolean, string).

When writing a list to an object array, OJSON validates the list, and returns an error if the Omnis data type of a column value is not suitable.

When parsing an array of objects, OJSON validates the data as it parses it, to make sure it is a single array of objects containing only simple types. In addition, OJSON adds columns on the fly, and if a column already exists makes sure the data in the JSON is of the same type as the already added column. This works best when all entries in the array are objects with identical members.

Static Methods

The OJSON object provides the following static methods:

OJSON.$jsontolistorrow()

OJSON.$jsontolistorrow(vData,[&cErrorText])
Parses the JSON array or object in vData (either binary (UTF8/16/32) or character) and returns a row or a list representing the JSON. Returns NULL and cErrorText if an error occurs.

OJSON.$listorrowtojson()

OJSON.$listorrowtojson(vListOrRow [,iEncoding=kUniTypeUTF8, &cErrorText, iOptions=kOJSONoptionNone]) converts the list or row to JSON. Returns JSON with specified encoding (UTF8, UTF16BE/LE, UTF32BE/LE or Char). Returns NULL and cErrorText for an error.

The iOptions parameter can be used to make $listorrowtojson process all members of a top-level row, and discard empty or null values appropriately, recursively descending into child lists and rows. The iOptions parameter can be one of the following constants, which can be summed together to get the desired result:

  1. kOJSONoptionNone (the default)
    0 - No option specified - results in the old behavior

  2. kOJSONoptionOmitEmpty
    1 - Omit empty values, objects and arrays from the output JSON

  3. kOJSONoptionOmitNull
    2 - Omit NULL values from the output JSON

OJSON.$couldbearray()

OJSON.$couldbearray(vData)
Returns true if vData (either binary (UTF8/16/32) or character) could possibly be a JSON array because its first character is [.

OJSON.$couldbeobject()

OJSON.$couldbeobject(vData)
Returns true if vData (either binary (UTF8/16/32) or character) could possibly be a JSON object because its first character is {.

OJSON.$formatjson()

OJSON.$formatjson(vData)
Parses the JSON in vData (either binary (UTF8/16/32) or character) and returns a formatted representation (or error message if parsing fails) suitable for use in a multi-line entry control.

The following static methods allow you to manipulate object arrays:

OJSON.$listtoobjectarray()

OJSON.$listtoobjectarray(lList[,iEncoding=kUniTypeUTF8,&cErrorText])
Writes a list with simple columns to an array of objects; returns JSON with specified encoding (UTF8,UTF16BE/LE,UTF32BE/LE or Character). Returns NULL and cErrorText for an error.

OJSON.$objectarraytolist()

OJSON.$objectarraytolist(vData[,&cErrorText])
Parses vData (binary (UTF8/16/32) or character). vData must be a JSON array of objects containing members with simple types. Returns a list representing JSON. Returns NULL and cErrorText for an error.

The following static methods allow you to manipulate an array of arrays:

OJSON.$listtoarrayarray()

OJSON.$listtoarrayarray(lList[,iEncoding=kUniTypeUTF8,&cErrorText]) writes a list with simple columns to an array of arrays; returns the JSON with specified encoding (UTF8, UTF16BE/LE, UTF32BE/LE or Character). Returns NULL and cErrorText for an error.

OJSON.$arrayarraytolist()

OJSON.$objectarraytolist(vData[,&cErrorText]) parses vData (binary (UTF8/16/32) or character). vData must be a JSON array of arrays containing members with simple types. Returns a list representing the JSON. Returns NULL and cErrorText for an error.

These methods only work with simple types as array members. $arrayarraytolist requires that each JSON array must have the same number of elements, and each JSON array member at a particular index must be of the same data type.

JSON External Component Object

After constructing the OJSON object, it represents an empty JSON object. The methods supported by the external component object (with the exception of $getlasterror()) all set an error code and error text if an error occurs during their execution. In addition, you can use the method $runtimerrors to set a flag that causes the component to generate a runtime error (entering the debugger if applicable) when an error occurs - this can be useful when developing code that uses OJSON. The object provides the following methods.

Note: in all of these descriptions, cMember is the member id of an entity in the JSON document tree:

$getjson([cMember,iEncoding=kUniTypeUTF8])

Returns the JSON for the OJSON object (when cMember is an empty string or omitted) or the specified array or object member (cMember) using the specified encoding.

$setjson(cMember,vData)

Sets the OJSON object (when cMember is an empty string) or the specified array or object member (cMember) to the JSON supplied in vData (either binary (UTF8/16/32) or character). Returns a Boolean, true for success.

$getlasterror([&cErrorText])

Returns the error code from the last OJSON object method executed; also optionally populates cErrorText with a description of the error.If no error occurred, returns zero and the error text is empty.

$runtimeerrors(bGenerate)

Call with true to cause a runtime error when a method returns an error (so the debugger is entered if applicable), or false to stop runtime errors. Returns previous value of bGenerate. Default is no runtime errors.

$listmemberids()

Returns a single column list of the member ids for all of the members.

$isobject(cMember)

Tests specified member. Returns true if the member is a JSON object.

$getobject(cMember)

Gets the specified object. Returns a row containing the object members or NULL if the member is not an object.

$setobject(cMember,wRow)

Sets the specified member to the object specified in wRow. Returns a Boolean, true for success.

$addmember(cMember,cNewMemberName,vValue)

Adds member cNewMemberName with value vValue to object cMember. Returns a Boolean, true for success.

$removemember(cMember,cMemberName)

Removes member cMemberName from object cMember. Returns a Boolean, true for success.

$hasmember(cMember,cMemberName)

Returns true if cMemberName is a member of object cMember.

$listmembers(cMember)

Returns a single column list which contains the member names of the object cMember. Returns NULL if cMember is not an object.

$isarray(cMember)

Tests specified member. Returns true if the member is a JSON array.

$getarray(cMember)

Gets the specified array. Returns NULL if the member is not an array, a single column list if the array elements all have the same primitive type or are NULL, or for mixed arrays a row with one column per array element.

$getarraylength(cMember)

Returns the number of elements in the array cMember. Returns zero if cMember is not an array.

$setarray(cMember,vListOrRow)

Sets specified member to an array.Accepts either a single column list or a row where the columns are the array elements (the latter allows for arrays of mixed types). Returns a Boolean, true for success.

$push(cMember,vValue)

Adds an element with value vValue to the end of the array cMember. Returns a Boolean, true for success.

$pop(cMember)

Removes the last element from the end of the array cMember and returns its value as a row variable. Returns NULL if cMember is not an array or if cMember is empty.

$isstring(cMember)

Tests specified member. Returns true if the member is a JSON string.

$getstring(cMember)

Gets specified string member. Returns JSON string value (empty if member is not a string). Unescapes JSON syntax.

$setstring(cMember,cString)

Sets specified member to JSON string with value cString. Returns a Boolean, true for success.

$isbool(cMember)

Tests specified member. Returns true if the member is a JSON Boolean.

$getbool(cMember)

Gets specified Boolean member. Returns Boolean corresponding to JSON Boolean (false if member is not a Boolean).

$setbool(cMember,bBool)

Sets specified member to JSON Boolean with value bBool. Returns a Boolean, true for success.

$isinteger(cMember)

Tests specified member. Returns true if the member is a JSON integer.

$getinteger(cMember)

Gets specified integer member. Returns integer 64 bit (zero if member is not integer).

$setinteger(cMember,iInt)

Sets specified member to JSON integer with value iInt. Returns a Boolean, true for success.

$isfloat(cMember)

Tests specified member. Returns true if the member is a JSON floating point value.

$getfloat(cMember)

Gets specified floating point member. Returns number floating dp (zero if member is not floating point).

$setfloat(cMember,nNum)

Sets specified member to JSON floating point with value nNum. Returns a Boolean, true for success.

$isnull(cMember)

Tests specified member. Returns true if it is null.

$setnull(cMember)

Sets the specified member to null. Returns a Boolean, true for success.