Json class
The Json class facilitates data exchange with JavaScript programs or other programs that suport the JSON format. JSON can be considered as an alternative encoding format to XML which is supported in SOUL by the XmlDoc API. The advantages of JSON over XML are:
- It is easier to use in JavaScript programs.
- It maps more naturally on to object-oriented structures, especially collections.
- It is lighter-weight. That is, data represented as JSON is typically more compact than the same data represented as XML and the JSON standard is considerably simpler than the XML standard.
All that said, there are many situations where XML is a better choice for an exchange format than JSON.
Json objects would typically be created either programmatically using JSON constructors or by parsing a JSON string sent from another platform. A Json object tree can be examined and manipulated using a set of Json functions and the resulting object tree can be serialized as a string. The Json parsing and serialization functions operate only on unicode so a separate step is required to encode/decode the data to/from a format suitable for network transfer, most commonly UTF-8.
The JsonType enumeration
The JsonType enumeration indicates the type of JSON data represented by a Json object. Json objects simulate JavaScript variables in that they are untyped so that the same variable can actually reference very different datatypes.
The values of the JsonType enumeration which correspond to the equivalent JSON datatypes are:
Null | A null object value. A Json object will never have a null value but the type of a null pointer is Null. |
---|---|
String | A unicode string value which can be set or retrieved from a SOUL Unicode variable or expression. |
Number | A number value which behaves very much like Model 204 Float variables. |
Array | An ordered but un-named collection of Json objects. |
Object | An ordered, named collection of Json objects. |
Note: As with all enumerations, the ToString method implicitly converts an enumeration value to a character string whose value is the name of the enumeration value. For more information about methods available to all enumerations, see Common enumeration methods.
Implicit conversions
A Json object can represent a number or a string. To create a Json string object one can use the String function and to create a Json number object one can use the Number function:
%json is object json ... %json = string("Argle bargle") ... %json = number(2.718281828459)
However, in many cases, one can assign an intrinsic number of string value directly to a Json object without the conversion function:
%json is object json ... %json = "Argle bargle" ... %json = 2.718281828459
The resulting type of the Json object is determined from the type of the source of the assignment. The Number and String functions can be useful if one wants to set the target Json object datatype to something different from the source type. Explicit assignment also occurs for Json parameters in methods. For example, if one had:
local function foobar(%json is object json) is float
One could call the method as
%x = %(local):foobar("Golden") ... %x = %(local):foobar(1.61803398874989)
Note that this provides a dynamically typed parameter capability that might be useful to SOUL programmers, even if not specifically interested in parsing or generating JSON strings.
While it would appear that there is also implicit conversion from boolean values, that's not really the case. In fact, there are Json class True and False functions that return boolean Json objects with the indicated value. So the following are valid:
%json = true %json = false %json = %(json):true %json = %(json):false
but the following is not
%json = %(boolean):true %json = %(boolean):false
And, since comparisons return a numeric value, if one wants to assign the result of a comparison to a Json object as a boolean, one must do something like:
%json = boolean(%war eq %peace)
Circular references
Json objects can have circular references also known as cycles in O-O terms. For example, one can create an array as:
%json is object json ... %json = array(13, 99, 44, array("Hickory", "Dickory", "Doc")) printText {~=%json}
which prints
%json=[13,99,44,["Hickory","Dickory","Doc"]]
However, if one then did:
%json(4):add(%json)
creating a circular reference to the array object, printing or serialize the object results in a
%json=[13,99,44,["Hickory","Dickory","Doc",[Circular]]]
While OK for debugging purposes, this is clearly not an ideal serialization because it provides no indication of what [Circular] refers to and, in fact, for complex object forests, there could be several [Circular] references, each of which might refer to a different object or array.
In fact, the JSON standard does not allow circular references. So, while an object forest with circular references can be used inside a SOUL program, such an object forest cannot be exchanged with another platform using JSON serialization. For such applications, it is recommended that a JSON object be serialized using the Stringify function. This function is almost identical to the ToString function (which is invoked implicitly when a JSON object is printed) except that if it encounters a circular reference it issues a:
Cancelling request: MSIR.0750: Class Json, function Stringify: Circular reference detected
While this is not ideal, it is probably preferable to sending out an invalid JSON string and having an error occur on a different platform, instead.
Inheritance
While it is technically possible to create a class that extends the Json class, since the Json class has no true constructors, only factory methods, it's impossible to really do much useful with such an extension class.
List of Json methods
List of Json methods contains a complete list of the class methods.