Difference between revisions of "MakeJSON"

(JSON Objects vs. Arrays: - changed flag from 8 to 9, EW18961)
m (Index order)
 
Line 45: Line 45:
 
  Variable data1 := [[Table]](Struct)( \z1, \z2 )
 
  Variable data1 := [[Table]](Struct)( \z1, \z2 )
  
You should think of <code>data1</code> as being like an instantiation of a class named <code>Struct</code>, which has two members <code>z1</code> and <code>z2</code>. The <code>z1</code> member of <code>data1</code> has a 2-D array indexed by <code>J, K</code>, and the <code>z2</code> member has a 2-D array indexed by <code>K, K</code>.
+
You should think of <code>data1</code> as being like an instantiation of a class named <code>Struct</code>, which has two members <code>z1</code> and <code>z2</code>. The <code>z1</code> member of <code>data1</code> has a 2-D array indexed by <code>J, K</code>, and <code>z2</code> has a 2-D array indexed by <code>I, K</code>.
  
If we don't specify the index order, you can't reliably predict which nesting of the array data will result.
+
If you don't specify the index order, you can't reliably predict which nesting you will get.
 
  [[MakeJSON]]( data1 ) &rarr;
 
  [[MakeJSON]]( data1 ) &rarr;
 
       { "z1": [[11, 12], [21, 22], [31, 32]],  
 
       { "z1": [[11, 12], [21, 22], [31, 32]],  

Latest revision as of 18:02, 27 June 2020


New to Analytica 5.0

This function requires the Analytica Enterprise edition or higher (i.e., higher editions are Analytica Optimizer, ADE or CubePlan]).

MakeJSON( x, indexOrder, objects, flags )

Returns text in JavaScript Object Notation (JSON)] format representing the data in «x». When there are multidimensional arrays, you can control the nesting order in the JSON text by specifying the indexes in the «indexOrder» parameter. When some indexes encode the member names of a JavaScript object, you should list those indexes in «objects». The optional «flags» parameter accepts an integer that encodes a bit-field of options, with these options.

  • 1 = Don't infer that 1-D arrays with textual indexes are objects.
  • 2 = reserved. Must be 0.
  • 4 = reserved. Should be 0.
  • 8 = Top-level element in the result can be a non-object.
  • 16 = Allow ragged arrays.

JSON Objects vs. Arrays

Consider the following array in Variable Biblio1984

MakeJSON Biblio1984.png

One way to encode this is JSON is an a JSON object.

MakeJSON( Biblio1984, objects: Biblio )
'{"title": "1984", "author": "George Orwell", "year": 1949, "pages": 336, "paperback": 1}'

A second way to encode the same array data is an a JSON array.

MakeJSON( Biblio1984, indexOrder:Biblio, flags:9 )
'["1984", "George Orwell", 1949, 336, 1]'

Because the top-most item in JSON text is supposed to a JSON object, this second example isn't strictly valid (the «flags»=8 option was required for this reason). But for information anywhere other than the outermost dimension of «x», the fact remains that the data in an Analytica array can be placed in either form -- JSON-object or JSON-array.

For any index in your data, you can make it explicit by listing the index in the «objects» parameter if you want it to produce a JSON object, or in the «indexOrder» parameter if you want it to produce a JSON-array for that index. When you don't set the «flags»=8 bit, one index will be selected as an object index, even if they are all listed in «indexOrder», just because JSON text is supposed to have the root be an object.

When «x» contains an index that you have not explicitly listed, it will infer that it should be an object when the «flags»=1 is not set, the array is 1-D, and the index has textual member names. Otherwise it will output it as an array without the index labels.

Index order

When an Analytica array has more that one-dimension, you should list the indexes in «indexOrder», with the index that should vary most slowly listed first. For example:

Index I := 1..4
Index  J := 1..3
Index K := ['k1', 'k2']
Variable z1 := 10 * J + @K
Variable z2 := 100*I + @K
Index Struct := ['z1', 'z2']
Variable data1 := Table(Struct)( \z1, \z2 )

You should think of data1 as being like an instantiation of a class named Struct, which has two members z1 and z2. The z1 member of data1 has a 2-D array indexed by J, K, and z2 has a 2-D array indexed by I, K.

If you don't specify the index order, you can't reliably predict which nesting you will get.

MakeJSON( data1 ) →
     { "z1": [[11, 12], [21, 22], [31, 32]], 
       "z2": [[101, 201, 301, 401], [102, 202, 302, 402]]
     }

Note: MakeJSON does not insert newlines or indents. The result was formatted above manually.

It may be that the application code receiving this expects the data to be in K-major order. In the above, z2 was as desired, but z1 was transposed. To ensure this, you need to specify the «indexOrder».

MakeJSON( data1, indexOrder: K, J, I ) →
{ "z1": [[11, 21, 31], [12, 22, 32]], 
  "z2": [[101, 201, 301, 401], [102, 202, 302, 402]]
}

When you list multiple indexes in the «objects» parameter, this also constrains the order, where the first index listed becomes the outer object. For example, given the following Analytica array

MakeJSON cat dog.png

listing Animal before Sex in «objects» creates nested objects as follows

MakeJSON(Counts, objects:Animal,Sex)→{"cat": {"Male": 12, "Female": 8}, "dog": {"Male": 4, "Female": 5}}

but listing them in the opposite order reverses the object nesting

MakeJSON(Counts, objects:Sex,Animal)→{"Male": {"cat": 12, "dog": 4}, "Female": {"cat": 8, "dog": 5}}

Mixed objects and arrays

(These rules apply to Analytica 5.2. Before that, it isn't legit to have object & array dimensions mixed for single arrays -- instead, you should use references to structure your object structures).

When a multi-dimensional array is transcribed into JSON at any level (each time there is a reference, you have a new multi-dimensional array to consider), each index of that array will be transcribed either as a JSON array or as a JSON object (i.e., either using brackets [ ] or using braces { } ). By using the «indexOrder» and «objects» parameters, you have control over which way each index is treated, as well as the nesting order. You could, for example, end up with an array of JSON objects, or a JSON object containing arrays for each member.

The rules for selecting whether an index is treated as an JSON object or JSON array is as follows:

  • An index listed in «objects» will be transcribed as an object.
  • When the array is 1-D and flags:1 is not set and the index labels are textual, an index not listed in «indexOrder_» is treated as an object.
  • When flags:8 is not set, the very first index of the entire JSON is an object.
  • Otherwise, it is transcribed as an array.

The rules for determining nesting order are as follows:

  • If index I appears before index J in the «indexOrder» parameter, then J will be nested inside I.
  • If index I appears before index J in the «objects» parameter, then J will be nested inside I.
  • When two indexes aren't explicitly ordered in one of the two parameters, objects are nested inside array dimensions (i.e., objects moved inward, array dimensions moved outward), so you'll end up with arrays of objects.
  • Finally, Analytica's internal canonical ordering is used. Since this is internal to Analytica, this is essentially an arbitrary ordering.

When you need to specify the nesting order between a JSON-array and a JSON-object dimension, list both corresponding indexes in the «indexOrder» parameter and list the index for the object in the «objects» parameter.

See Also

Comments


You are not allowed to post comments.