JSON Convert R←{X}⎕JSON Y

This function imports and exports data in JavaScript Object Notation (JSON) Data Interchange Format1.

JSON supports a limited number of data types and there is not a direct correspondence between JSON and APL data structures. In particular:

These differences are catered for in various ways as discussed below.

If specified, X must be a numeric scalar with the value 0 (import JSON) or 1 (export JSON). If X is not specified and Y is a character array, X is assumed to be 0 (import); otherwise it is assumed to be 1 (export).

Other options for ⎕JSON are Format, Compact, Null, HighRank and Dialect which are specified using the Variant operator . See Variant. The Principal Option is Format.

The Dialect Variant option is either 'JSON' (the default) or 'JSON5'. The latter enables JSON5 extensions on import and export.

JSON Import (X is 0)

Y is a character vector or matrix in JSON format. There is an implied newline character between each row of a matrix.

The content of the result R depends upon the Format variant which may be 'D' (the default) or 'M'.

If Format is 'D' (which stands for "data") the JSON described by Y is converted to APL object(s) and R is an array or a namespace containing arrays and sub-namespaces.

If Format is 'M' (which stands for "matrix") the result R is a matrix whose columns contain the following:

[;1] depth
[;2] name (for JSON object members)
[;3] value
[;4] JSON type (integer: see below)

Table 45: JSON data types are as follows:

Type Description
1 Object
2 Array
3 Numeric
4 String
5 Null
6 No APL equivalent (represented by character string)
7 JavaScript Object (export only)
Duplicate Names

The JSON standard says that members of a JSON object should have unique names and that different implementations behave differently when there are duplicates. Dyalog handles duplicate names as follows:

Examples

      ⍴JSON
18 19
      JSON
{                  
  "a": {           
    "b": [         
      "string 1",  
      "string 2"   
    ],             
    "c": true,     
    "d": {         
      "e": false,  
      "f⍺": [       
        "string 3",
        123,       
        1000.2,    
        null       
      ]            
    }              
  }                
}                  

Import as Data (Format 'D')

      j←⎕JSON JSON
      j
#.[JSON object]
      j.⎕NL 9
a
      j.a.⎕NL 2
b
c
      j.a.b
┌────────┬────────┐
│string 1│string 2│
└────────┴────────┘
      j.a.c
┌────┐
│true│
└────┘
      j.a.⎕NL 9
d
      j.a.d.⎕NL 2 ⍝ Note that f⍺ is an invalid APL name
e       
⍙f⍙9082⍙
      j.a.d.e
┌─────┐
│false│
└─────┘
      j.a.d.⍙f⍙9082⍙
┌────────┬───┬──────┬──────┐
│string 3│123│1000.2│┌────┐│
│        │   │      ││null││
│        │   │      │└────┘│
└────────┴───┴──────┴──────┘

Import as Matrix (Format 'M')

      (⎕JSON⍠'M')JSON
┌─┬──┬────────┬─┐
│0│  │        │1│
├─┼──┼────────┼─┤
│1│a │        │1│
├─┼──┼────────┼─┤
│2│b │        │2│
├─┼──┼────────┼─┤
│3│  │string 1│4│
├─┼──┼────────┼─┤
│3│  │string 2│4│
├─┼──┼────────┼─┤
│2│c │┌────┐  │6│
│ │  ││true│  │ │
│ │  │└────┘  │ │
├─┼──┼────────┼─┤
│2│d │        │1│
├─┼──┼────────┼─┤
│3│e │┌─────┐ │6│
│ │  ││false│ │ │
│ │  │└─────┘ │ │
├─┼──┼────────┼─┤
│3│f⍺│        │2│
├─┼──┼────────┼─┤
│4│  │string 3│4│
├─┼──┼────────┼─┤
│4│  │123     │3│
├─┼──┼────────┼─┤
│4│  │1000.2  │3│
├─┼──┼────────┼─┤
│4│  │┌────┐  │5│
│ │  ││null│  │ │
│ │  │└────┘  │ │
└─┴──┴────────┴─┘

JSON Export (X is 1)

Y is the data to be exported as JSON and may be an array, a namespace or a matrix representation of JSON such as would have been produced by JSON Import with Format 'M'. Y is interpreted according to the Format variant which may be 'D' (the default) or 'M'.

⎕JSON will signal DOMAIN ERROR if Y is incompatible with the specified (or implied) value of Format.

If Format is M, the data values in Y[;3] must correspond precisely with the JSON types specified in Y[;4]as specified in the following table.

Y[;4] (Type) Y[;3] (Value)
1 Empty array
2 Empty array
3 Numeric scalar
4 Character vector
5 Null
6 Enclosed character vector
7 Enclose character vector

R is a character vector whose content depends upon the value of the Compact variant.

Compact Description
0 The JSON text is padded with spaces and new lines for readability.
1 The JSON text is compacted into its minimal form..

The HighRank variant option may be used to instruct ⎕JSON to pre-process higher rank arrays into a form that can be represented by JSON. Note that if necessary, the transformation is applied recursively throughout the high-rank array(s) specified by Y.

HighRank Description
'Split' High rank data is split into nested vectors.
'Error' Higher rank data is rejected (DOMAIN ERROR)

The name of any namespace member that begins with and otherwise conforms to the conversion format used for JSON object names will be demangled.

Example

      j             ⍝ See above
#.[JSON object]
      ⍴JS←1 ⎕JSON j
94
      JS
{"a":{"b":["string 1","string 2"],"c":true,"d":{"e":false,"f⍺":["string 3",123,1000.2,null]}}}

      1(⎕JSON⍠'Compact' 0) j
{
  "a": {
    "b": [
      "string 1",
      "string 2"
    ],
    "c": true,
    "d": {
      "e": false,
      "f⍺": [
        "string 3",
        123,
        1000.2,
        null
      ]
    }
  }
}

If there are any mis-matches between the values in Y[;3] and the types in Y[;4], ⎕JSON will signal DOMAIN ERROR and report the first row where there is a mis-match (⎕IO sensitive) as illustrated in the following example.

Example

      M←(⎕JSON⍠'Format' 'M')'{"values": [ 75, 300 ]}'
      M
┌─┬──────┬───┬─┐
│0│      │   │1│
├─┼──────┼───┼─┤
│1│values│   │2│
├─┼──────┼───┼─┤
│2│      │75 │3│
├─┼──────┼───┼─┤
│2│      │300│3│
└─┴──────┴───┴─┘

      M[3;3]←⊂'75' ⍝ character not numeric

      M            ⍝ but looks the same as before
┌─┬──────┬───┬─┐
│0│      │   │1│
├─┼──────┼───┼─┤
│1│values│   │2│
├─┼──────┼───┼─┤
│2│      │75 │3│
├─┼──────┼───┼─┤
│2│      │300│3│
└─┴──────┴───┴─┘
      1 (⎕JSON⍠ 'Format' 'M')M
DOMAIN ERROR: Value does not match the specified type in row 3
      1(⎕JSON⍠'Format' 'M')M
     ∧

High Rank Example

      d
┌─────┬─────────────────────────┐
│1 2  │ABC                      │
│A B  │DEF                      │
├─────┼─────────────────────────┤
│1 2 3│1            0.5         │
│4 5 6│0.3333333333 0.25        │
│     │                         │
│     │0.2          0.1666666667│
│     │0.1428571429 0.125       │
└─────┴─────────────────────────┘
      1 ⎕JSON d
DOMAIN ERROR: JSON export: the right argument cannot be converted (⎕IO=1)
      1 ⎕JSON d
        ∧
      1 (⎕JSON⍠'HighRank' 'Split') d
[[[[1,2],"AB"],["ABC","DEF"]],[[[1,2,3],[4,5,6]],...

JavaScript Objects

The following example illustrates how JavaScript objects may be exported.

In the example, the object is a JavaScript function which is specified by the contents of an enclosed character vector. Note that in this case Dyalog performs no validation of the code itself.

Example

     'Slider' ⎕NS ''
      Slider.range←⊂'true'         ⍝ Note the ⊂
      Slider.min←0
      Slider.max←500
      Slider.values←75 300
     
      fn1←' function( event, ui ) {'
      fn2←'$( "#amount" ).val( "$" + ui.values[ 0 ] +'
      fn2,←' " - $" + ui.values[ 1 ] );}'
      
      Slider.slide←,/fn1 fn2 ⍝ Enclosed character vec
      ⍴JS←1 ⎕JSON Slider
159
      JS
{"max":500,"min":0,"range":true,"slide": function( event, ui ) {$( \"#amount\" ).val( \"$\" + ui.values[ 0 ] + \" - $\" + ui.values[ 1 ] );},"values":[75,300]}

JSON Name Mangling

When Dyalog converts from JSON to APL data, and a member of a JSON object has a name which is not a valid APL name, it is renamed.

Example:

In this example, the JSON describes an object containing two numeric items, one named a (which is a valid APL name) and the other named 2a (which is not):

{"a": 1, "2a": 2}

When this JSON is imported as an APL namespace using ⎕JSON, Dyalog converts the name 2a to a valid APL name. The name mangling algorithm creates a name beginning with .

      (⎕JSON'{"a": 1, "2a": 2}').⎕NL 2
a  
⍙2a

When Dyalog exports JSON it performs the reverse name mangling, so:

      1 ⎕JSON ⎕JSON'{"a": 1, "2a": 2}'
{"a":1,"2a":2}

Should you need to create and decode these names directly,7162⌶ provides the same name mangling and un-mangling operations. See JSON Translate Name.

      0(7162⌶)'2a'
⍙2a
      1(7162⌶)'⍙2a'
2a