github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/gen/includes/for-loop-json-tips.inc.md (about)

     1  ### Tips when writing JSON inside for loops
     2  
     3  One of the drawbacks (or maybe advantages, depending on your perspective) of
     4  JSON is that parsers generally expect a complete file for processing in that
     5  the JSON specification requires closing tags for every opening tag. This means
     6  it's not always suitable for streaming. For example
     7  
     8  ```
     9  » ja [1..3] -> foreach i { out ({ "$i": $i }) }
    10  { "1": 1 }
    11  { "2": 2 }
    12  { "3": 3 }
    13  ```
    14  
    15  **What does this even mean and how can you build a JSON file up sequentially?**
    16  
    17  One answer if to write the output in a streaming file format and convert back
    18  to JSON
    19  
    20  ```
    21  » ja [1..3] -> foreach i { out (- "$i": $i) }
    22  - "1": 1
    23  - "2": 2
    24  - "3": 3
    25  
    26  » ja [1..3] -> foreach i { out (- "$i": $i) } -> cast yaml -> format json
    27  [
    28      {
    29          "1": 1
    30      },
    31      {
    32          "2": 2
    33      },
    34      {
    35          "3": 3
    36      }
    37  ]
    38  ```
    39  
    40  **What if I'm returning an object rather than writing one?**
    41  
    42  The problem with building JSON structures from existing structures is that you
    43  can quickly end up with invalid JSON due to the specifications strict use of
    44  commas.
    45  
    46  For example in the code below, each item block is it's own object and there are
    47  no `[ ... ]` encapsulating them to denote it is an array of objects, nor are
    48  the objects terminated by a comma.
    49  
    50  ```
    51  » config -> [ shell ] -> formap k v { $v -> alter /Foo Bar }
    52  {
    53      "Data-Type": "bool",
    54      "Default": true,
    55      "Description": "Display the interactive shell's hint text helper. Please note, even when this is disabled, it will still appear when used for regexp searches and other readline-specific functions",
    56      "Dynamic": false,
    57      "Foo": "Bar",
    58      "Global": true,
    59      "Value": true
    60  }
    61  {
    62      "Data-Type": "block",
    63      "Default": "{ progress $PID }",
    64      "Description": "Murex function to execute when an `exec` process is stopped",
    65      "Dynamic": false,
    66      "Foo": "Bar",
    67      "Global": true,
    68      "Value": "{ progress $PID }"
    69  }
    70  {
    71      "Data-Type": "bool",
    72      "Default": true,
    73      "Description": "ANSI escape sequences in Murex builtins to highlight syntax errors, history completions, {SGR} variables, etc",
    74      "Dynamic": false,
    75      "Foo": "Bar",
    76      "Global": true,
    77      "Value": true
    78  }
    79  ...
    80  ```
    81  
    82  Luckily JSON also has it's own streaming format: JSON lines (`jsonl`). We can
    83  `cast` this output as `jsonl` then `format` it back into valid JSON:
    84  
    85  ```
    86  » config -> [ shell ] -> formap k v { $v -> alter /Foo Bar } -> cast jsonl -> format json
    87  [
    88      {
    89          "Data-Type": "bool",
    90          "Default": true,
    91          "Description": "Write shell history (interactive shell) to disk",
    92          "Dynamic": false,
    93          "Foo": "Bar",
    94          "Global": true,
    95          "Value": true
    96      },
    97      {
    98          "Data-Type": "int",
    99          "Default": 4,
   100          "Description": "Maximum number of lines with auto-completion suggestions to display",
   101          "Dynamic": false,
   102          "Foo": "Bar",
   103          "Global": true,
   104          "Value": "6"
   105      },
   106      {
   107          "Data-Type": "bool",
   108          "Default": true,
   109          "Description": "Display some status information about the stop process when ctrl+z is pressed (conceptually similar to ctrl+t / SIGINFO on some BSDs)",
   110          "Dynamic": false,
   111          "Foo": "Bar",
   112          "Global": true,
   113          "Value": true
   114      },
   115  ...
   116  ```
   117  
   118  #### `foreach` will automatically cast it's output as `jsonl` _if_ it's STDIN type is `json`
   119  
   120  ```
   121  » ja [Tom,Dick,Sally] -> foreach name { out Hello $name }
   122  Hello Tom
   123  Hello Dick
   124  Hello Sally
   125  
   126  » ja [Tom,Dick,Sally] -> foreach name { out Hello $name } -> debug -> [[ /Data-Type/Murex ]]
   127  jsonl
   128  
   129  » ja [Tom,Dick,Sally] -> foreach name { out Hello $name } -> format json
   130  [
   131      "Hello Tom",
   132      "Hello Dick",
   133      "Hello Sally"
   134  ]
   135  ```