﻿# JSON

**xcall JSON, opcode, \{, parameters...\}**

JSON performs various JSON-related utility functions.

**Parameters**

_opcode_  \[in\]

specifies operation to be performed, described in detail below.

u **Opcode 1: Load a JSON string into an ordered map**

**xcall JSON, 1, handle, status, jsontext\$, \$ordmap()**

**Parameters**

_handle_  (B4+ or F)  \[out\]

returns a handle to the JSON structure in memory (for future expansion)

_status_ (Signed [Num](num.md))  \[out\] 

returns the status of the operation:

| **Code** | **Status** |
|------|------|
| \>= 0 | indicates success (# nodes parsed) |
| < 0 | indicates an error: |
| \-1 | out of memory |
| \-3 | out of JSON library handles |
| \-5 | invalid map reference |
| \-6 | ordered maps not supported in this A-Shell version |




_jsontext\$ _ ([String](string.md)) \[in\]

The JSON object to load into the ordered map. Note that you can use the function Fn'FileToStr\$(fspec\$) from [fnfilestr.bsi in SOSLIB\[907,10\]](https://bitbucket.org/microsabio/soslib/src/master/907010/fnfilestr.bsi) to load a JSON file into _jsontext\$_.

_\$ordmap() _ (ordered map)  \[out\]

Returns an ordered map representation of the JSON object, using XPATH-like syntax, consisting of a key representing the path to the value and the value representing the value. For example, the following JSON excerpt describing a program menu bar ...

\{ "menu": \{

    "header": "SVG Viewer",

    "items": \[

        \{"id": "Open"\},

        \{"id": "OpenNew", "label": "Open New"\},

        null,

        \{"id": "ZoomIn", "label": "Zoom In"\},

        ...



... would be converted to an ordered map something like this:

/menu/header -> SVG Viewer

/menu/items\[1\]/id -> Open

/menu/items\[2\]/id -> OpenNew

/menu/items\[2\]/label -> Open New

/menu/items\[4\]/id -> ZoomIn

/menu/items\[4\]/label -> Zoom In

...



Note that the output _\$ordmap()_ is not automatically pre-cleared, so if using the same _\$ordmap()_ for additional calls to this function, you'll need to use the .CLEAR statement first.



u **Opcode 2: Free the JSON memory associated with the HANDLE**

**xcall JSON, 2, handle, status**

**Parameters**

_handle_  (B4+ or F)  \[in\]

handle returned from _opcode_ 1

_status_  (Signed [Num](num.md))  \[out\] - 

0 for success



u **Opcode 3: Escape the JSON text**

**xcall JSON, 3, status, jsontext\$**

**Parameters**

_status_  (Signed [Num](num.md))  \[out\]

returns the number of special characters escaped

_jsontext\$_  ([String](string.md))  \[in/out\]

JSON text, both source and destination

This function applies JSON escaping rules to special characters in the specified JSONTEXT\$, returning the resulting string in the same variable. Note that since escaping increases the size of the text, the JSONTEXT\$ parameter should be sufficiently large to handle the worst case, which could be up to six times the original, or be a dynamic string. The algorithm assumes that the JSONTEXT\$ is encoded using the Latin1 character set, and supports the following:

| **Character** | **Esc Seq** | **** | **Character** | **Esc Seq** |
|------|------|------|------|------|
| " (quote) | \\" |  | chr(13) (CR) | \\r |
| \\ (backslash) | \\\\ |  | chr(9) (tab) | \\t |
| / (slash) | \\/ |  | chr(1) - chr(31) | \\u0001 - \\u001F |
| chr(8) (backspace) | \\b |  | chr(160) - chr(255) | \\u00A0 - \\U00FF |
| chr(12) (formfeed) | \\f |  |  |  |




Note that aside from eliminating the need to reinvent the wheel in a BASIC function, the subroutine operates much faster than you could possibly do in BASIC.



u **Opcode 4: Unescape the JSON text**

**xcall JSON, 4, status, jsontext\$**

**Parameters**

_status_  (Signed [Num](num.md))  \[out\]

returns the number of escaped characters unescaped

_jsontext\$_  ([String](string.md))  \[in/out\]

JSON text, both source and destination

This is the reverse of _opcode_ 3, converting the escaped sequences into their original raw form. Note that here the output will never be longer than the input.



u **Opcode 5: Form a "name":"value" pair**

**xcall JSON, 5, status, name\$, value\$, jsonpair\$ \{,flags\}**

**Parameters**

_status_  

not used

_name\$_  ([String](string.md))  \[in\]

the name part of the name:value pair

_value\$_  ([String](string.md))  \[in\]

the value part of the name:value pair

_jsontext\$_  ([String](string.md))  \[out\]

the "name":"value" result is returned here

_flags  _([Num](num.md))  \[in\]

optional flags from the table below

| **Symbol** | **Value** | **Description** |
|------|------|------|
| XJSONF\_NUMBER | \&h0001 | treat _value\$_ as a number (don't quote it) |
| XJSONF\_LCS | \&h0002 | fold _name\$_ lower case |
| XJSONF\_UCS | \&h0004 | fold _name\$_ upper case |
| XJSONF\_NOTRIM | \&h0010 | don't trim leading/trailing spaces from value (else do) |
| XJSONF\_NONULLVAL | \&h0020 | If _value\$_="", output will be a null string (without a trailing comma) instead of "name":"". |
| XJSONF\_NOCOMMA | \&h0040 | no trailing comma (else output pair ends with a comma) |
| **Definition file: **[ashinc:json.def](https://bitbucket.org/microsabio/soslib/src/master/907016) | | 



Although this may seem like a minimal operation that can easily be accomplished in a simple BASIC function, as with _opcode_ 3 and 4, the big advantage is speed, which might matter when dealing with large datasets involving hundreds of thousands or millions of such pairs.

Note that unless the XJSONF\_NOCOMMA flag is specified, the output will contain a trailing comma so that you can call the function in a loop without having to explicitly output a comma between each pair.

**History**

2025 October, A-Shell 7.0.1779  Change XJSONF\_NONULLVAL behavior; previously output "".

2021 October, A-Shell 6.5.1708:  Routine added to A-Shell.