Json class: Difference between revisions
No edit summary |
|||
(13 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
The <var>Json</var> class facilitates data exchange with [http://en.wikipedia.org/wiki/JavaScript JavaScript] programs or other programs that support the [http://en.wikipedia.org/wiki/JSON JSON] format. JSON can be considered as an alternative encoding format to [http://en.wikipedia.org/wiki/XML XML] which is supported in SOUL by the [[XmlDoc API]]. The advantages of JSON over XML are: | |||
The <var>Json</var> class facilitates data exchange with [http://en.wikipedia.org/wiki/JavaScript JavaScript] programs or other programs that | |||
<ul> | <ul> | ||
<li>It is easier to use in JavaScript programs.</li> | <li>It is easier to use in JavaScript programs.</li> | ||
<li>It maps more naturally on to object-oriented structures, especially collections.</li> | <li>It maps more naturally on to object-oriented structures, especially collections.</li> | ||
<li>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.</li> | |||
<li>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.</li> | |||
</ul> | </ul> | ||
All that said, there are many situations where XML is a better choice for an exchange format than JSON. | All that said, there are many situations where XML is a better choice for an exchange format than JSON. | ||
Json objects | <var>Json</var> objects are typically created either programmatically using JSON constructors or by parsing a JSON string sent from another platform. A <var>Json</var> object tree can be examined and manipulated using a set of <var>Json</var> functions, and the resulting object tree can be serialized as a string. The <var>Json</var> 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 [http://en.wikipedia.org/wiki/UTF-8 UTF-8]. | ||
== | <blockquote class="note"><b>Notes:</b> | ||
The <var>JsonType</var> [[Enumerations|enumeration]] indicates the type of JSON data represented by a Json object. Json objects simulate JavaScript variables in that they are untyped so | <ul> | ||
<li>One slight oddity in the JSON support is that JSON variable names, unlike any other variable names, cannot contain a period. So <code>%my.json.variable</code> is not a valid JSON variable name. | |||
<li>The Json class is new in version 7.6 of Model 204. | |||
</ul> | |||
</blockquote> | |||
==JsonType enumeration== | |||
The <var>JsonType</var> [[Enumerations|enumeration]] indicates the type of JSON data represented by a <var>Json</var> object. <var>Json</var> objects simulate JavaScript variables in that they are untyped, so the same variable can actually reference very different datatypes. | |||
The values of the <var>JsonType</var> enumeration which correspond to the equivalent JSON datatypes are: | The values of the <var>JsonType</var> enumeration which correspond to the equivalent JSON datatypes are: | ||
<table class="thJustBold"> | <table class="thJustBold"> | ||
<tr><th>Null</th><td>A null object value. A Json object will never have a null value but the type of a null pointer is Null.</td></tr> | <tr><th>Null</th> | ||
<tr><th>String</th><td>A unicode string value which can be set or retrieved from a SOUL [[Unicode]] variable or expression.</td></tr> | <td>A null object value. A <var>Json</var> object will never have a null value, but the type of a null pointer is Null.</td></tr> | ||
<tr><th>Number</th><td>A number value which behaves very much like Model 204 [[Float class|Float]] variables.</td></tr> | |||
<tr><th>Array</th><td>An ordered but | <tr><th>String</th> | ||
<tr><th>Object</th><td>An ordered, named collection of Json objects.</td></tr> | <td>A unicode string value which can be set or retrieved from a SOUL [[Unicode]] variable or expression.</td></tr> | ||
<tr><th>Number</th> | |||
<td>A number value which behaves very much like Model 204 [[Float class|Float]] variables.</td></tr> | |||
<tr><th>Boolean</th> | |||
<td>A value of <var>True</var> or <var>False</var>.</td></tr> | |||
<tr><th>Array</th> | |||
<td>An ordered but unnamed collection of <var>Json</var> objects.</td></tr> | |||
<tr><th>Object</th> | |||
<td>An ordered, named collection of <var>Json</var> objects.</td></tr> | |||
</table> | </table> | ||
Line 26: | Line 46: | ||
==Implicit conversions== | ==Implicit conversions== | ||
A Json object can represent a number or a string. To create a Json string object | A <var>Json</var> object can represent a number or a string. | ||
The variable name for a <var>Json</var> object follows the naming conventions for SOUL variables, except it cannot contain a period. | |||
To create a <var>Json</var> string object, you can use the [[String (Json function)|String function]]. To create a <var>Json</var> number object, you can use the [[Number (Json function)|Number function]]: | |||
<p class="code">%json is object json | <p class="code">%json is object json | ||
... | ... | ||
Line 33: | Line 57: | ||
%json = number(2.718281828459) | %json = number(2.718281828459) | ||
</p> | </p> | ||
However, in many cases, | However, in many cases, you can assign an intrinsic number of string value directly to a <var>Json</var> object without the conversion function: | ||
<p class="code">%json is object json | <p class="code">%json is object json | ||
... | ... | ||
Line 40: | Line 64: | ||
%json = 2.718281828459 | %json = 2.718281828459 | ||
</p> | </p> | ||
The resulting type of the Json object is determined from the type of the source of the assignment. The Number and String functions | The resulting type of the <var>Json</var> object is determined from the type of the source of the assignment. The <var>Number</var> and <var>String</var> functions are useful if you want to set the target <var>Json</var> object datatype to something different from the source type. Explicit assignment also occurs for <var>Json</var> parameters in methods. For example, if you had: | ||
<p class="code">local function foobar(%json is object json) is float | <p class="code">local function foobar(%json is object json) is float | ||
</p> | </p> | ||
You could call the method as: | |||
<p class="code">%x = %(local):foobar("Golden") | <p class="code">%x = %(local):foobar("Golden") | ||
... | ... | ||
%x = %(local):foobar(1.61803398874989) | %x = %(local):foobar(1.61803398874989) | ||
</p> | </p> | ||
Note that this provides a dynamically typed parameter capability that might be useful to SOUL | Note that this provides a dynamically typed parameter capability that might be useful to a SOUL programmer, even if not specifically interested in parsing or generating JSON strings. | ||
<p> | <p> | ||
While it | While it might appear that there is also implicit conversion from boolean values, that is not really the case. In fact, there are <var>Json</var> class [[True (Json function)|True]] and [[False (Json function)|False]] functions that return boolean <var>Json</var> objects with the indicated value. So the following are valid:</p> | ||
<p class="code">%json = true | <p class="code">%json = true | ||
%json = false | %json = false | ||
%json = %(json):true | %json = %(json):true | ||
%json = %(json):false | %json = %(json):false | ||
</p> | </p> | ||
But the following is <i><b>not valid</b></i>: | |||
<p class="code">%json = %(boolean):true | <p class="code">%json = %(boolean):true | ||
%json = %(boolean):false | %json = %(boolean):false | ||
</p> | </p> | ||
And, since comparisons return a numeric value, if | And, since comparisons return a numeric value, if you want to assign the result of a comparison to a <var>Json</var> object as a boolean, you must do something like: | ||
<p class="code">%json = boolean(%war eq %peace) | <p class="code">%json = boolean(%war eq %peace) | ||
</p> | </p> | ||
==Circular references== | |||
<var>Json</var> objects can have circular references, also known as cycles in object oriented terms. For example, you can create an array as: | |||
<p class="code">%json is object json | |||
... | |||
%json = array(13, 99, 44, array("Hickory", "Dickory", "Doc")) | |||
printText {~=%json} | |||
</p> | |||
The print result is: | |||
<p class="code">%json=[13,99,44,["Hickory","Dickory","Doc"]] | |||
</p> | |||
However, if you then did the following, creating a circular reference to the array object: | |||
<p class="code">%json(4):add(%json) | |||
</p> | |||
Printing the object results in: | |||
<p class="code">%json=[13,99,44,["Hickory","Dickory","Doc",[Circular]]] | |||
</p> | |||
While alright for debugging purposes, this is clearly not an ideal serialization, because: | |||
<ul> | |||
<li>It provides no indication of what <code>[Circular]</code> refers to. </li> | |||
<li>For complex object forests, there could be several <var>[Circular]</var> references, each of which might refer to a different object or array. </li> | |||
</ul> | |||
<p> | |||
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 (Json function)|Stringify function]]. This function is almost identical to the [[ToString (Json function)|ToString function]] (which is invoked implicitly when a JSON object is printed), except that if it encounters a circular reference it cancels the request: | |||
</p> | |||
<p class="code">Cancelling request: MSIR.0750: Class Json, function Stringify: Circular reference detected | |||
</p> | |||
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== | ==Inheritance== | ||
Although it is technically possible to create a class that extends the <var>Json</var> class, it is impossible to do much that is useful with such an extension class, because the <var>Json</var> class has no true constructors, only factory methods. | |||
==List of Json methods== | ==List of Json methods== | ||
[[List of Json methods]] contains a complete list of the class methods. | [[List of Json methods]] contains a complete list of the class methods. | ||
[[Category:System classes]] | [[Category:System classes]] |
Latest revision as of 20:13, 26 April 2018
The Json class facilitates data exchange with JavaScript programs or other programs that support 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 are typically 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.
Notes:
- One slight oddity in the JSON support is that JSON variable names, unlike any other variable names, cannot contain a period. So
%my.json.variable
is not a valid JSON variable name.- The Json class is new in version 7.6 of Model 204.
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 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. |
Boolean | A value of True or False. |
Array | An ordered but unnamed 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.
The variable name for a Json object follows the naming conventions for SOUL variables, except it cannot contain a period.
To create a Json string object, you can use the String function. To create a Json number object, you can use the Number function:
%json is object json ... %json = string("Argle bargle") ... %json = number(2.718281828459)
However, in many cases, you 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 are useful if you want 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 you had:
local function foobar(%json is object json) is float
You 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 a SOUL programmer, even if not specifically interested in parsing or generating JSON strings.
While it might appear that there is also implicit conversion from boolean values, that is 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 valid:
%json = %(boolean):true %json = %(boolean):false
And, since comparisons return a numeric value, if you want to assign the result of a comparison to a Json object as a boolean, you must do something like:
%json = boolean(%war eq %peace)
Circular references
Json objects can have circular references, also known as cycles in object oriented terms. For example, you can create an array as:
%json is object json ... %json = array(13, 99, 44, array("Hickory", "Dickory", "Doc")) printText {~=%json}
The print result is:
%json=[13,99,44,["Hickory","Dickory","Doc"]]
However, if you then did the following, creating a circular reference to the array object:
%json(4):add(%json)
Printing the object results in:
%json=[13,99,44,["Hickory","Dickory","Doc",[Circular]]]
While alright for debugging purposes, this is clearly not an ideal serialization, because:
- It provides no indication of what
[Circular]
refers to. - 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 cancels the request:
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
Although it is technically possible to create a class that extends the Json class, it is impossible to do much that is useful with such an extension class, because the Json class has no true constructors, only factory methods.
List of Json methods
List of Json methods contains a complete list of the class methods.