-
Notifications
You must be signed in to change notification settings - Fork 154
Expand file tree
/
Copy pathChatScript-Json.html
More file actions
565 lines (552 loc) · 56.4 KB
/
ChatScript-Json.html
File metadata and controls
565 lines (552 loc) · 56.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta name="generator" content="pandoc" />
<title></title>
<style type="text/css">code{white-space: pre;}</style>
<style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
</style>
</head>
<body>
<h1 id="chatscript-json-manual">ChatScript JSON Manual</h1>
<p>© Bruce Wilcox, mailto:gowilcox@gmail.com www.brilligunderstanding.com <br>Revision 11/21/2021 cs11.6</p>
<h1 id="real-world-json">Real World JSON</h1>
<p>JSON (JavaScript Object Notation) is an open standard format using human-readable text to transmit data objects over the web. It is a common standard largely replacing XML which is too wordy and hard to read. JSON has primitive datatypes (text without doublequotes that cannot contain any whitespace). These are null, false, true, integers, and floats. The string datatype is a sequence of characters in double quotes. JSON also has two datatypes that represent collections of values, the array and the object. A JSON array is a list of JSON datatypes separated by commas and placed within square brackets <code>[]</code>, e.g.,</p>
<pre><code>[ A, 2, [ help, life], [] ]</code></pre>
<p>Indices of an array start at 0, so the above has as values:</p>
<pre><code>[0] = A
[1] = 2
[2] = an array of 2 values
[3] = an empty array</code></pre>
<p>Note that arrays can hold values of different types. Arrays have no hole in indexing and usually ordered and retain that order, but they work out of order as well (^Jsonmerge can alter the order). A JSON object is a list of key-value pairs separated by commas and placed within curly braces <code>{}</code>, e.g.,</p>
<div class="sourceCode"><pre class="sourceCode json"><code class="sourceCode json"><span class="fu">{</span>
<span class="dt">"key1"</span><span class="fu">:</span> <span class="dv">1</span><span class="fu">,</span>
<span class="dt">"bob"</span><span class="fu">:</span> <span class="st">"help"</span><span class="fu">,</span>
<span class="dt">"1"</span><span class="fu">:</span> <span class="dv">7</span><span class="fu">,</span>
<span class="dt">"array"</span><span class="fu">:</span> <span class="ot">[</span><span class="dv">1</span><span class="ot">,</span> <span class="dv">2</span><span class="ot">,</span> <span class="dv">3</span><span class="ot">]</span><span class="fu">,</span>
<span class="dt">"object12"</span><span class="fu">:</span> <span class="fu">{}</span>
<span class="fu">}</span></code></pre></div>
<p>Each key is a string (must be encased in double quotes) and joined to an ending colon. Again types can be mixed in the values. <code>{}</code> is the empty object, just as <code>[]</code> is the empty array. Key-value pairs have no guaranteed order and may shuffle around if you manipulate the structure. You can nest arrays and objects inside each other.</p>
<h1 id="chatscript-json">ChatScript & JSON</h1>
<p>JSON is an excellent language to represent more complex ChatScript facts as well as interact with the web. ChatScript can convert back and forth between the JSON text string passed over the web and ChatScript facts that represent the structure internally. If you tried to create facts using ^createfact(), you would find making the data shown below extremely difficult and non-obvious. Though it can be done. But as JSON, it is easy to create facts to represent the structure and to access pieces of it.</p>
<div class="sourceCode"><pre class="sourceCode json"><code class="sourceCode json"><span class="fu">{</span>
<span class="dt">"firstName"</span><span class="fu">:</span> <span class="st">"John"</span><span class="fu">,</span>
<span class="dt">"lastName"</span><span class="fu">:</span> <span class="st">"Smith"</span><span class="fu">,</span>
<span class="dt">"age"</span><span class="fu">:</span> <span class="dv">25</span><span class="fu">,</span>
<span class="dt">"address"</span><span class="fu">:</span> <span class="fu">{</span>
<span class="dt">"streetAddress"</span><span class="fu">:</span> <span class="st">"21 2nd Street"</span><span class="fu">,</span>
<span class="dt">"city"</span><span class="fu">:</span> <span class="st">"New York"</span><span class="fu">,</span>
<span class="dt">"state"</span><span class="fu">:</span> <span class="st">"NY"</span><span class="fu">,</span>
<span class="dt">"postalCode"</span><span class="fu">:</span> <span class="st">"10021-3100"</span>
<span class="fu">},</span>
<span class="dt">"phoneNumbers"</span><span class="fu">:</span> <span class="ot">[</span>
<span class="fu">{</span>
<span class="dt">"type"</span><span class="fu">:</span> <span class="st">"home"</span><span class="fu">,</span>
<span class="dt">"number"</span><span class="fu">:</span> <span class="st">"212 555-1234"</span>
<span class="fu">}</span><span class="ot">,</span>
<span class="fu">{</span>
<span class="dt">"type"</span><span class="fu">:</span> <span class="st">"office"</span><span class="fu">,</span>
<span class="dt">"number"</span><span class="fu">:</span> <span class="st">"646 555-4567"</span>
<span class="fu">}</span>
<span class="ot">]</span><span class="fu">,</span>
<span class="dt">"children"</span><span class="fu">:</span> <span class="ot">[]</span><span class="fu">,</span>
<span class="dt">"spouse"</span><span class="fu">:</span> <span class="kw">null</span>
<span class="fu">}</span></code></pre></div>
<p>JSON facts are triples where the subject is always the name of a JSON object or array. For objects, the verb of the fact is the name of a field and the object is its value. Such a structure might be composed of these facts: <code>internal CS (jo-3 name Robert) (jo-3 age 10) (jo-3 gender male)</code> Note that CS does not need to put double quotes around the values or even the field names (unless the field name has spaces or other unusual characters within it).</p>
<p>This would correspond to a JSON string that looks like this:</p>
<pre><code>{ "name": "Robert", "age": 10, "gender": "male"}</code></pre>
<p>Actually, the "age 10" fact in ChatScript could represent either what was shown above or:</p>
<pre><code>{ "name": "Robert", "age": "10", "gender": "male"}</code></pre>
<p>For arrays, the verb of the fact is the numeric index in the array and the object is the value. Such a structure might be composed of these facts:</p>
<pre><code>(ja-5 0 Robert)
(ja-5 1 Terry)
(ja-5 2 Paula)</code></pre>
<p>This would correspond to a JSON string that looks like this:</p>
<pre><code>[ "Robert", "Terry", "Paula"]</code></pre>
<p>CS has rich support for creating JSON data. You must create the top level array or object, but after that you can just do assignments somewhat arbitrarily, with CS automatically creating new subobjects or subarrays as needed. E.g. Also note that CS assignments onto object fields do not require you double quote the field name (unless the name as spaces within it or other unusual characters).</p>
<pre><code>$_x = ^jsoncreate(TRANSIENT object)
$_x.field[] = 5
$_x.name.age.birthdate = "January 5, 2020"</code></pre>
<p>In the above, the scripter has explicitly created a transient JSON object. The 2nd line assignment automatically creates a transient array to save as the value of <code>field</code> and then inserts the value 5 into it. The 3rd line assignment automatically creates a field called name with a JSON object, and that object gets a field called age, and that object gets a field called birthdate which is assigned the text string.</p>
<h3 id="json-cs-anomolies">JSON CS ANOMOLIES</h3>
<p>Because JSON has distinct data types as values (primitives, text strings, etc) and CS represents everything as text strings, there are some issues in moving back and forth in representation. Whereas JSON shows all strings encased in double quotes, when stored as values in CS the double quotes are always removed. And JSON primitives <code>false</code>, <code>true</code>, and numbers are also just strings. Therefore JSON primitive <code>2</code> and the JSON string <code>"2"</code> are the same to CS. To maintain data type information, JSON facts have flag bits that describe how to treat the object value of the fact. This is automatically handled by CS and normally you have no reason to pay any attention to it.</p>
<p>But when you copy a value out of the fact onto a CS variable, the type data goes away. This is not a problem for CS, except when you want to store the CS variable back into a JSON structure. Then YOU become responsible for knowing the type. CS will assume any of its values that match a JSON primitive will be that, so you need to encase them in double-quotes if you want them to be stored as JSON strings. CS will automatically store everything else as JSON strings and when exporting them to text, will automatically encase them in double quotes. For example,</p>
<pre><code>$_x = ^jsoncreate(TRANSIENT object)
$_x.value = true # JSON boolean primitive
^jwrite($_x) => {"value": true}
$_y = $_x.value
$_x.value = $_y
^jwrite($_x) => {"value": true}
$_x.value = "true" # JSON string true
^jwrite($_x) => {"value": "true"}
$_y = $_x.value
$_x.value = $_y
^jwrite($_x) => {"value": true}
$_x.value = "true" # JSON string true
^jwrite($_x) => {"value": "true"}
$_y = ^join(\" $_x.value \")
$_x.value = $_y
^jwrite($_x) => {"value": "true"}</code></pre>
<p>All this breaks down a bit for the JSON <code>null</code> primitive and the empty string "". CS does not distinguish between having no value and having a value which has no characters. And CS uses <code>null</code> to mean clear a value entirely. So to create a JSON null value, use the special word <code>json_null</code>. You can use that directly in a JSON assignment, or you can put it as the value of a CS variable which eventually gets used in a JSON assignment.</p>
<pre><code>$_x.value = null # remove the JSON field called value
$_x.value = "null" # assign text string null to field value
$_x = null # remove any value from variable
$_x.value = json_null # special value meaning json null primitive</code></pre>
<p>This just leaves us with the awkwardness of the empty string. You can't store an empty string onto a CS variable. Instead you store a string with two double quotes. Which CS itself always treats as just that, a two-character string. But when assigned into a JSON structure, any double quoted string has its double quotes stripped. So in JSON we CAN have an empty string. No problem yet. The problem comes in the other direction. Assigning this JSON empty string onto a CS variable clears it (it acts like null). And then putting that variable back onto a JSON structure will save JSON null. So you have to manually track what you want, if you want it.</p>
<pre><code>$_x.value = "" # JSON empty string
$_y = 5
$_y = $_x.value # clears $_y (acts like null)
$_x.value = $_y # assigns JSON null</code></pre>
<h3 id="json-facts">JSON FACTS</h3>
<p>Since JSON data structures are implemented as facts, they can use the ^query abilities just as ordinary facts can. Whereas in JSON you can only access data going top down, with CS you can equally access data at any level directly querying on some field name. So depending on how you name a field and whether or not the field only exists for a single object, you might be able to query directly to it.</p>
<p>Note that JSON has no mechanism for sharing JSON subtrees. Hence anytime you create a JSON fact structure in CS, the facts will all be unique. You do this like this:</p>
<pre><code> $_tmp = ^createfact($$jsonobject newfield $$jsondata (FACTTRANSIENT JSON_OBJECT_FACT JSON_OBJECT_VALUE) )</code></pre>
<p>If $$jsonobject is a json object name, you add a field called newfield whose value is a JSON object, thus joining the trees. If you serialize (write into text) these two JSON objects they will become completely separate structures when read back in (JSON doesn't share).</p>
<h2 id="accessing-the-web-with-json">Accessing the web with JSON</h2>
<p>You will learn how to create JSON structures below. The other key to a web-enabled CS is ^jsonopen(). To see how easy it is to talk to the web, just look at this code.</p>
<pre><code># The cleanest way to build json data
$_var = ^jsoncreate(transient object)
$_var.fieldname = $myvar
An alternative limited to max output buffer size (~80K):
$_var = ^jsonparse(^"{ fieldname: $myvar }")
And now to send data upstream:
$_url = ^"http://myHost:myIP"
$_userAgent = ^"User-Agent: %bot, ChatScript”
$_header = ^" ~Accept: application/json
$_userAgent
~Content-Type: application/json "
$_response = ^jsonopen(transient POST $_url $_var $_header $_userAgent) </code></pre>
<h2 id="jsonflags---optional-1st-arg-to-some-json-routines">JSONFLAGS - Optional 1st arg to some JSON routines</h2>
<p>Routines that will create facts for JSON will by default create them as transients (they die at end of volley unless you work to save them). You can override this default by saying <code>permanent</code> or <code>transient</code> or <code>boot</code>. This applies to <code>^jsonopen</code>, <code>^jsonparse</code>, <code>^jsoncreate</code>, <code>^jsonobjectinsert</code>, <code>^jsonarrayinsert</code>, <code>^jsoncopy</code>, <code>jsonmerge</code>.</p>
<p>Json arrays all start with the name 'ja-' and json objects all start with the name 'jo-'. The next letter indicates the storage media. 't' means transient and the structure dies at the end of the volley. 'b' means boot and the data moves to the boot later at the end of the volley. Anything else (e.g. an immediate digit) means the structure is permanent and is stored in the user's topic file.</p>
<p>You can also add a flag <code>safe</code> (described later) to <code>^jsonparse</code>, <code>^jsonobjectinsert</code>, <code>^jsonarraydelete</code>. You can also add a flag <code>unique</code> to <code>^jsonarrayinsert</code>. You can also add <code>duplicate</code> to ^jsonobjectinsert.</p>
<p>When multiple flags are desired, put them into a simple string, <code>"DUPLICATE PERMANENT"</code>. Case doesn't matter.</p>
<p>When you want to add a reference to a normal factid (as is returned by ^createfact) you can add the flag <code>AUTODELETE</code></p>
<p>You can also assign user flags by listing <code>USER_FLAG1</code>, through <code>USER_FLAG4</code> as a flag as well. The JSON fact will have that flag on it, which you can use in conjunction with <code>^query</code> to limit what matches can be found.</p>
<h3 id="jsonstorage-argument"><code>^jsonstorage</code>( argument )</h3>
<p>This expects a json array or object name and returns <code>permanent</code>, <code>transient</code>, <code>boot</code> or fails completely depending on what is given it.</p>
<h3 id="jsonparse-jsonflags-string"><code>^jsonparse</code>( {JSONFLAGS} string )</h3>
<p><code>string</code> is a JSON text string (as might be returned from a website) and this parses into facts. It returns the name of the root node JSON composite. This name will look like this:</p>
<ul>
<li><code>ja-0</code> – a json array numbered <code>0</code>.</li>
<li><code>jo-0</code> – a json object numbered <code>0</code>.</li>
</ul>
<p>Note that the above names are true only for PERMANENT JSON objects. Transient ones will be named like <code>ja-t0</code> and <code>jo-t0</code>.</p>
<p>As new JSON composites are created during a volley, the numbers increase to keep them all distinct. JSON composites are all created as transient facts and will die at the end of the volley unless you do something to explictly keep them (typically <code>^jsongather</code> into some factset and then saving that OR using that to remove all their transient flags OR using <code>^delete()</code> to destroy the facts in the set).</p>
<p>If you are keeping JSON across volleys, you should use the optional Json flags argument to make sure numbering never collides (normally the numbers start back at 0 for each new volley).</p>
<p>Real world JSON has stricter requirements on its format than CS does.</p>
<p>While CS will output strict JSON, you can input slack JSON. You do not need to put commas between elements of an array or object. And you do not need to put quotes around a key name. So the following is legal text form:</p>
<pre><code>[a b {bob: 1 sue: 2}]</code></pre>
<p>Formally JSON has specific primitives named true, false, and null, that systems may care about, but to CS they are nothing special. Numbers in JSON can be integer or have a decimal point and an exponent. CS does not currently support exponent notation, so you can only do: <code>1325</code> or <code>566.23</code>.</p>
<p>JSON originally required a JSON string be a composite of some kind. Now it allows any JSON type to be a JSON document. CS sticks to the original requirement, because passing around a single value as JSON is pretty useless.</p>
<p>Once you have a JSON fact structure, you can go the opposite direction and convert it back into a string or display it visually.</p>
<p>CS accepts extended JSON syntax for parsing into a json fact structure. Any place you have an object value, you can refer to a ChatScript user or match variable and that value will be substituted in. E.g.,</p>
<pre><code>^jsonparse("{ a: $var, b: _0 }")</code></pre>
<p>Note you should use a regular quoted string and not a function string like <code>^"{ a: $var, b: _0 }"</code>. If you use a function string, substitution will happen before calling ^jsonparse. Which might be a problem if you had something like this:</p>
<pre><code>^jsonparse("{ a: $var, b: _0aba }").</code></pre>
<p>where you wanted the value of <code>b</code> to be <code>"_0aba"</code>. Had you used an active string, the _0 would have been replaced with its contents.</p>
<p>Also, you can use json dereference operators to take apart an existing json structure and use values of it in the current one. If $_y points to a json structure, then</p>
<pre><code>^jsonparse(" opensquiggle a: $var, b: $_y.e[2] closesquiggle ")
(saying squiggles because Latex print complains if I use real ones)</code></pre>
<p>would find a json object reference on <code>$_y</code>, get the e field, and get the 3rd array value found there.</p>
<p>An initial argument of <code>safe</code> will locate the correct end of the data for json parsing, allowing you to pass excess data. This is important for passing in json data in OOB information. OOB information comes in <code>[]</code> and Json itself uses <code>[]</code> at times, so it would be impossible to find the correct end of pattern with normal pattern matching. Instead just do:</p>
<pre><code>u: ( \[ _* ) and call ^jsonparse(safe _0)</code></pre>
<p>This will figure out where the OOB marker actually is and only parse within it. You can add NOFAIL before the string argument, to tell it to return null but not fail if a dereference path fails cannot be found.</p>
<pre><code>^jsonparse(transient NOFAIL "{ a: $var, b: _0.e[2] }")</code></pre>
<p>Note: You cannot send JSON text as normal input from a user because CS tokenization is set to handle human input. So doing something like this as input will not work:</p>
<pre><code>doLogin {"token": "myid", "accounts": ["whatever"]}</code></pre>
<p>Instead you should call a website using <code>^jsonopen</code> which will automatically convert returned JSON data into internal CS data. Or you can pass JSON data on input via OOB notation:</p>
<pre><code>[ {"token": "myid", "accounts": ["whatever"]}] User message</code></pre>
<p>and then have a pattern to grab the OOB data and call <code>jsonparse</code> with it (using SAFE as a parameter). OOB input is not subject to human tokenization behavior, spellchecking, etc.</p>
<p>Note: There is a limit to how much JSON you can pass as OOB data nominally, because it is considered a single token. You can bypass this limit by asking the tokenizer to directly process OOB data, returning the JSON structure name instead of all the content. Just enable <code>JSON_DIRECT_FROM_OOB</code> on the <code>$cs_token</code> value and if it finds OOB data that is entirely JSON, it will parse it and return something like <code>jo-t1</code> or <code>ja-t1</code> in its place. Eg. <code>[ { "key": "value} ]</code> will return tokenized as <code>[jo-t1]</code>.</p>
<pre><code>u: GIVEN_JSON(< \[ _* \] ^JsonKind('_0)) $$json = '_0 </code></pre>
<p>then you can do $$json.field directly.</p>
<p>Note: <code>^jsonparse</code> autoconverts backslash-unnnn into corresponding the utf8 characters.</p>
<p>Similarly, you could pass JSON data directly as part of user input. But user input normally is limited to 254 tokens AFTER oob is seen. To be able to pass complex JSON data as part of the user message (because the oob is often controlled by host system so not available per user message), you can now put in user input the word <code>json</code> and follow that with a JSON structure of arbitrary size. That structure will be completely converted to the corresponding JSON internal fact structures and the simple JSON structure name returned. So</p>
<pre><code>my input value is JSON {x:y,b:z} here </code></pre>
<p>will become</p>
<pre><code>my input value is JSON jo-3 here</code></pre>
<p>and jo-3 will have the json structure.</p>
<h2 id="jsonformatstring"><code>jsonformat</code>(string)</h2>
<p>Because technically JSON requires you put quotes around field names (though various places ignore that requirement) and because CS doesn't, the function takes in a slack json text string and outputs a strict one.</p>
<h2 id="accessing-json-structures">Accessing JSON structures</h2>
<h2 id="direct-access-via-json-variables-myvar.field-and-myvar">Direct access via JSON variables <code>$myvar.field</code> and <code>$myvar[]</code></h2>
<p>If a variable holds a JSON object value, you can directly set and get from fields of that object using dotted notation. This can be a fixed static fieldname you give or a user variable value or a match variable value (quoted or unquoted): <code>$myvar.$myfield</code> is legal, as is <code>$myvar._0</code> or <code>$myvar.'_0</code>.</p>
<p>Dotted notation is cleaner and faster than <code>^jsonpath</code> and <code>jsonobjectinsert</code> and for get, has the advantage that it never fails, it only returns null if it can't find the field. If the path does not contain a json object at a level below the top, one will automatically be created if trying to do assignment, and have the same transient/permanent property as the immediately containing object. If the top level variable is not currently an object, assignment will fail. CS will not create an object for you because it doesn't know if it should be transient or permanent.</p>
<pre><code>$x = $$obj.name.value.data.side
$$obj.name.value.data.side = 7</code></pre>
<p>Similarly you can access JSON arrays using array notation:</p>
<pre><code>$x = $$array[5]
$x = $$array[$_tmp]
$$obj.name[4] += 3
$$obj.$_kind[4] += 3
$$obj._0[4] += 3
$$obj.'_0[4] += 3</code></pre>
<pre><code>$x.foo[] = Bruce</code></pre>
<p>If foo is currently undefined, the system will create a JSON array for you, with permanency that matches the JSON object of $x. You cannot do $x[] and have this happen because at the top level the system does not know what permanency to use. Once there is a JSON array in $x.foo, assignments with <code>foo[]</code> will add elements to the array. You can designate the index only if it will be the next index in succession.</p>
<pre><code> $_x[] = 0 # creates array element 0
$_x[1] = 1 # accepts array element 1 creation request
$_x[3] = 3 # will fail - must be in sequence</code></pre>
<p>You can also do</p>
<pre><code> $_array1 += $_array2 # copies contents of array2 into array1
$_array1 += value # adds value into array1</code></pre>
<p>Adding an element to an array using these notations will automatically select DUPLICATE entries being legal. If you want the insertion to be unique, use ^jsonarrayinsert(UNIQUE xxx xxx) OR in your botmacro change the default by doing</p>
<pre><code> $cs_json_array_defaults = #JSON_ARRAY_UNIQUE </code></pre>
<p>The only restriction on arrays is that you cannot add a new array index value without using ^jsonarrayinsert as you are not allowed to create discontiguous indices.</p>
<p><strong>NOTE</strong> JSON is normally a non-recursive structure with no shared pointers. But ChatScript allows you to store references to JSON structures in multiple places of other JSON structures. This has its hazards. It presents no problem when transcribing to text for a website using <code>^jsonwrite</code> . And when you have something like this:</p>
<pre><code>$x = ^jsoncreate(object)
$y = ^jsoncreate(object)
$x.field = $y
$x.field1 = $y
$x.field = null</code></pre>
<p>Assuming that a JSON structure is not available in multiple places, the assignment of null (or any other value) to a field that already has a JSON structure will normally cause the old value structure to be fully deleted, since it's only reference is removed. And the system does check and delete the structure if it is not referred to by some other JSON field. But there are limits. The system has no idea if you have a pointer to it in a variable. Or if it is part of a pathological indirection sequence like this:</p>
<pre><code>$x = ^jsoncreate(object)
$y = ^jsoncreate(object)
$x.field = $y
$y.field = $x
$x.field = null</code></pre>
<p>The two structures point to each other, each only once. So assigning null will kill off both structures.</p>
<p>Assigning <code>null</code> will remove a JSON key entirely. Having a null value and not having the key are the same from ChatScript's perspective (but not from JSON's)'</p>
<h4 id="accessing-opposite-ends-of-json-structures">Accessing opposite ends of JSON structures</h4>
<p>For an array, obviously $array[0] returns one end of the array, and you can get the index of The other end by doing</p>
<pre><code> $_tmp = ^length($array) - 1
$array[$_tmp]</code></pre>
<p>But a convenient shortcut is</p>
<pre><code> $array[-1]</code></pre>
<p>For objects, $object[0] returns the name of the most recent field added and $object[-1] returns the name of the first field added.</p>
<h4 id="using-a-word-as-a-field-name-rather-than-as-indirection">using a $word as a field name rather than as indirection</h4>
<p>Just escape the $.</p>
<pre><code>$data.\$varname = hello </code></pre>
<h3 id="jsonkinditem"><code>^jsonkind</code>(item)</h3>
<p>If item is the name of a json array, it returns <code>array</code>. If item is the name of a json object, it returns <code>object</code>. Otherwise it fails.</p>
<h3 id="jsonmerge-kind-struct1-struct2"><code>^jsonmerge</code>( {kind} struct1 struct2)</h3>
<p>Takes two json arrays or two json objects and adds unique elements of struct2 into struct1 recursively.</p>
<p>If <code>kind</code> is <code>key</code> and the two structs are arrays of objects, then unique objects from the second array are added to the first array (this is the default). Unique meaning that the first property from the object does not exist. If <code>kind</code> is <code>key-value</code> is like <code>key</code> but the uniqueness test is extended to the property value as well. If <code>kind</code> is <code>sum</code> and the two structs are objects, then the values for the same property name in the two objects are added together. If <code>kind</code> is <code>sumif</code> is like <code>sum</code> but items in <code>struct1</code> are only kept if they are also in <code>struct2</code>.</p>
<h3 id="jsoncountstruct-depth"><code>^jsoncount</code>(struct depth)</h3>
<p>Walks the given JSON structure, displaying it, except that for arrays arising after depth, just the count of elements is shown</p>
<h3 id="jsonpath-string-id"><code>^jsonpath</code>( string id )</h3>
<ul>
<li><code>string</code> is a description of how to walk JSON.</li>
<li><code>id</code> is the name of the node you want to start at (typically returned from <code>^jsonopen</code> or <code>^jsonparse</code>).</li>
</ul>
<p>Array values are accessed using typical array notation like <code>[3]</code> and object fields using dotted notation. A simple path access might look like this: <code>[1].id</code> which means take the root object passed as id, e.g., <code>ja-1</code>, get the 2nd index value (arrays are 0-based in JSON).</p>
<p>That value is expected to be an object, so return the value corresponding to the id field of that object. In more complex situations, the value of id might itself be an object or an array, which you could continue indexing like <code>[1].id.firstname</code>.</p>
<p>You can walk an array by using <code>[$_index]</code> and varying the value of <code>$_index</code>.</p>
<p>When you access an array element, you have to quote the text because it consists of multiple tokens to CS which breaks off <code>[</code> and <code>]</code>. If you are just accesing an object field of something, you can quote the string or just type it directly</p>
<pre><code>^jsonpath(.id $object2)
^jsonpath(".id" $object2)</code></pre>
<p>Of course you don't always have to start at the root. If you know what you want is going to become object 7 eventually, you could directly say .id given <code>jo-7</code> and the system would locate that and get the id field. Likewise if you know that key names are somehow unique, you could query for them directly using</p>
<pre><code>^query(direct_v ? verbkey ?)</code></pre>
<p>Or even if the key is not unique you can restrict matches to facts having the <code>JSON_OBJECT_FACT</code> flag.</p>
<pre><code>^query(directflag_v ? verbkey ? 1 ? ? ? JSON_OBJECT_FACT)</code></pre>
<p>Be aware that when <code>^jsonpath</code> returns the value of an object key, when the value is a simple word, it just returns the word without doublequotes (since CS just stores information as a single word). But if the value contains whitespace, or JSON special characters, that may mess up if you pass it to <code>^JSONFormat</code>. You can get <code>^jsonpath</code> to return dangerous data as a string with double quotes around it if you add a 3rd argument "safe" to the call.</p>
<pre><code>^jsonpath(".name" $_jsonobject safe)</code></pre>
<h3 id="jsonpath"><code>^jsonpath</code></h3>
<p>Generally speaking the direct access methods are clearer than using this function.</p>
<p>Can also return the actual factid of the match, instead of the object of the fact. This would allow you to see the index of a found array element, or the json object/array name involved. Or you could use ^revisefact to change the specific value of that fact (not creating a new fact). Just add * after your final path, eg</p>
<pre><code>^jsonpath(.name* $$obj)
^jsonpath(.name[4]* $$obj)</code></pre>
<p>Correspondingly, if you are trying to dump all keys and values of a JSON object, you could do a query like this:</p>
<pre><code>@0 = ^query(direct_s $_jsonobject ? ?)
^loop()
{
_0 = ^first(@0all)
and then you have _1 and _2 as key and value
}</code></pre>
<p>If you need to handle the full range of legal keys in json, you can use text string notation like this <code>^jsonpath(."st. helen".data $tmp)</code>.</p>
<p>You may omit the leading . of a path and CS will by default assume it</p>
<pre><code>^jsonpath("st. helen".data $tmp)</code></pre>
<h3 id="jsonloopjsonstruct-var1-var2">^jsonloop($jsonstruct $var1 $var2)</h3>
<p>This is like ^loop, but explicitly for json data. It is faster and cleaner than writing a loop. A normal loop might look like:</p>
<pre><code> $_count = ^length($_jsonarray)
^loop($_count)
{
$_count -= 1
$_value = $_jsonarray[$_count]
...
}</code></pre>
<p>And similarly for a JSON object one might want:</p>
<pre><code> $_count = ^length($_jsonobject)
^loop($_count)
{
$_count -= 1
$_jsonfield = $_jsonobject[$_count]
$_value = $_jsonobject.$_jsonfield
...
}</code></pre>
<p>But for large numbers of elements (eg a thousand +) this is ineffient because it has to search for each element each time. The efficient way is:</p>
<pre><code> ^jsonloop($_jsonobject $_field $_value)
{
...
}</code></pre>
<p>where the loop runs most recent entry to least recent, putting the field name in <code>$_field</code> and its value in <code>$_value</code>. Similarly for a jsonarray it does the index as <code>$_field</code> and <code>$_value</code> is its value.</p>
<p>You can choose (or annotate) which way the loop runs by adding an optional 3rd argument OLD or NEW.</p>
<pre><code>^jsonloop($_jsonarray $_index $_value OLD) will walk oldest first (i.e. index 0 and increasing).
^jsonloop($_jsonarray $_index $_value NEW) will walk newest first (i.e. index max and decreasing).</code></pre>
<h3 id="length-jsonid"><code>^length</code>( jsonid )</h3>
<p>Returns the number of top-level members in a json array or object.</p>
<h2 id="printing-json-structures">Printing JSON structures</h2>
<h3 id="jsonwrite-plain-name"><code>^jsonwrite</code>( {plain} name )</h3>
<p>name is the name from a json fact set (either by <code>^jsonpart</code>, <code>^jsonopen</code>, or some query into such structures). The result is the corresponding JSON string (as a website might emit), without any linefeeds. <code>plain</code> is an optional first argument that makes it write out less noisy JSON that CS already accepts, ie field names and string values dont need double quotes around them unless they have certain characters in them (like spaces and semi-colons and escape characters). This makes data output from CS and intended to be read back into CS easier to read. So</p>
<pre><code> jo-5 which is {"value":"color"} prints as {value:color}</code></pre>
<h3 id="jsontree-name-depth-array"><code>^jsontree</code>( name {depth} {array})</h3>
<p>name is the value returned by <code>^jsonparse</code> or <code>^jsonopen</code> or some query into such structures. It displays a tree of elements, one per line, where depth is represented as more deeply indented. Objects are marked with <code>{}</code> as they are in JSON. Arrays are marked with <code>[]</code>.</p>
<p>The internal name of the composite is shown immediately next to its opening punctuation. Optional depth number restricts how deep it displays. 0 (default) means all. 1 means just top level.</p>
<p>Optional "array" means show number of array elements rather than the elements themselves at any depth below depth.</p>
<h2 id="json-structure-manipulation">JSON structure manipulation</h2>
<p>You can build up a JSON structure without using <code>^jsonparse</code> if you want to build it piece by piece. And you can edit existing structures.</p>
<h3 id="jsoncreate-jsonflags-type"><code>^jsoncreate</code>( {JSONFLAGS} type )</h3>
<p>Type is either <code>array</code> or <code>object</code> and a json composite with no content is created and its name returned. See <code>^jsonarrayinsert</code>, <code>^jsonobjectinsert</code>, and <code>^jsondelete</code> for how to manipulate it. See writeup earlier about optional json flags.</p>
<h3 id="jsonarrayinsert-jsonflags-arrayname-value"><code>^jsonarrayinsert</code>( {JSONFLAGS} arrayname value )</h3>
<p>Given the name of a json array and a value, it adds the value to the end of the array. See writeup earlier about optional json flags. If you use the flag unique then if value already exists in the array, no duplicate will be added.</p>
<h3 id="jsonarraydelete-index-value-arrayname-value"><code>^jsonarraydelete</code>( [<code>INDEX</code>, <code>VALUE</code>] arrayname value )</h3>
<p>This deletes a single entry from a JSON array. It does not damage the thing deleted, just its member in the array.</p>
<ul>
<li>If the first argument is <code>INDEX</code>, then value is a number which is the array index (0 ... n-1).</li>
<li>If the first argument is <code>VALUE</code>, then value is the value to find and remove as the object of the json fact.</li>
</ul>
<p>You can delete every matching <code>VALUE</code> entry by adding the optional argument <code>ALL</code>. Like: <code>^jsonarraydelete("VALUE ALL" $array 4)</code></p>
<p>If there are numbered elements after this one, then those elements immediately renumber downwards so that the array indexing range is contiguous.</p>
<p>If the key has an existing value then if the value is a json object it will be recursively deleted provided its data is not referenced by some other fact (not by any variables). You can suppress this with the <code>SAFE</code> flag. <code>^jsonarraydelete(SAFE $obj $key)</code>.</p>
<h3 id="jsonarraysize-name"><code>^jsonarraysize</code>( name )</h3>
<p>deprecated in favor of ^length</p>
<h3 id="jsontextfactid"><code>^jsontext</code>(factid)</h3>
<p>^jsontext adds quotes if object of fact is a json text and FAILS if object is not a json fact.</p>
<p>CS represents json text as ordinary unquoted text, but text that looks like float numbers would be subject to possible float truncations or expansion of digits. This preserves it as text.</p>
<h3 id="jsoncopy-name"><code>^jsoncopy</code>( name )</h3>
<p>Given the name of a json structure, makes a duplicate of it. If it is not the name of a json structure, it merely returns what you pass it.</p>
<h3 id="jsonmerge-creation_arg-control-arg1-arg2"><code>^jsonmerge</code>( {creation_arg} control arg1 arg2 )</h3>
<p>^jsonmerge take two json structures and perform a top level merge. The result is a copy of the first argument, with top level fields augmented with fields from arg2 not found in arg1. Optional first argument is the standard one for many Json creation functions.</p>
<p>Control describes how to merge fields of json objects. <code>key</code> means if arg1 already has this key, ignore the corresponding field from arg2. <code>key-value</code> means add in the field and value unless they are the same.</p>
<p>You can also request the system to sum values of fields of objects with control values of <code>sum</code> or <code>sumif</code>.</p>
<h3 id="jsonobjectinsert-jsonflags-objectname-key-value"><code>^jsonobjectinsert</code>( {JSONFLAGS} objectname key value )</h3>
<p>inserts the key value pair into the object named. The key does not require quoting. Inserting a json string as value requires a quoted string. Duplicate keys are ignored unless the optional 1st argument <code>DUPLICATE</code> is given. See writeup earlier about optional json flags.</p>
<p>If the key has an existing value and <code>DUPLICATE</code> is not a factor, then if the value is a json object it will be recursively deleted provided its data is not referenced by some other fact (not by any variables). You can suppress this with the <code>SAFE</code> flag. <code>jsonobjectinsert(SAFE $obj $key null)</code>.</p>
<h3 id="jsondelete-factid"><code>^jsondelete</code>( factid )</h3>
<p>deprecated in favor of ^delete</p>
<h3 id="jsongather-fact-set-jsonid-level"><code>^jsongather</code>( {fact-set} jsonid {level})</h3>
<p>takes the facts involved in the json data (as returned by <code>^jsonparse</code> or <code>^jsonopen</code>) and stores them in the named factset.<br />
This allows you to remove their transient flags or save them in the users permanent data file.</p>
<p>You can omit fact-set as an argument if you are using an assignment statement: <code>@1 = ^jsongather(jsonid)</code></p>
<p><code>^Jsongather</code> normally gathers all levels of the data recursively. You can limit how far down it goes by supplying <code>level</code>. Level 0 is all. Level 1 is the top level of data. Etc.</p>
<h3 id="jsonlabel-label"><code>^jsonlabel</code>( label )</h3>
<p>assigns a text sequence to add to jo- and ja- items created thereafter. See System functions manual.</p>
<h3 id="readfile-tab-filepath-fn-and-readfile-line-filepath-fn"><code>^readfile</code>( TAB filepath {'^fn}) and <code>^readfile</code>( LINE filepath '^fn)</h3>
<p>reads a tsv (tab delimited spreadsheet file) and returns a JSON array representing it. The lines are all objects in an array. The line is an object where non-empty fields are given as field indexes. The first field is 0. Empty fields are skipped over and their number omitted.</p>
<p>If an optional 3rd parameter of a function name is given, the code does not create a JSON structure to return. Instead it calls the function with each field of a line being an argument. This is sort of analogous to <code>:document</code> mode in that you can potentially read large amounts of data in a single volley and may need to use <code>^memorymark</code> and <code>^memoryfree</code> to manage the issue.</p>
<p><code>^readfile ( LINE filepath 'function)</code> reads a file and passes each line untouched as the sole argument to the function.</p>
<p>Formerly called ^jsonreadfile (still accepted).</p>
<h3 id="jsonundecodestring-string"><code>^jsonundecodestring</code>( string )</h3>
<p>removes all json escape markers back to normal for possible printout to a user. This translates \n to newline, \r to carriage return, \t to tab, and \" to a simple quote.</p>
<h2 id="web-json">WEB JSON</h2>
<h3 id="jsonopen-jsonflags-kind-url-postdata-header-timeout"><code>^jsonopen</code>( {JSONFLAGS} kind url postdata header {timeout})</h3>
<p>this function queries a website and returns a JSON datastructure as facts. It uses the standard CURL library, so it's arguments and how to use them are generally defined by CURL documentation and the website you intend to access. See writeup earlier about optional json flags.</p>
<table style="width:81%;">
<colgroup>
<col width="18%" />
<col width="62%" />
</colgroup>
<thead>
<tr class="header">
<th align="center">parameter</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center"><code>kind</code></td>
<td>is <code>POST</code>, <code>GET</code>, <code>POSTU</code>, <code>GETU</code>, <code>PUT</code>, <code>DELETE</code> corresponding to the usual meanings of Get and Post and url-encoded forms.</td>
</tr>
<tr class="even">
<td align="center"><code>url</code></td>
<td>is the url to query</td>
</tr>
<tr class="odd">
<td align="center"><code>postdata</code></td>
<td>is either "" if this is not a post or is the data to send as post or put</td>
</tr>
<tr class="even">
<td align="center"><code>header</code></td>
<td>is any needed extra request headers or "". Multiple header entries must be separated by a tilde</td>
</tr>
<tr class="odd">
<td align="center"><code>timeout</code></td>
<td>optional seconds limitation for connection and then for transfer. else $cs_jsontimeout rules</td>
</tr>
</tbody>
</table>
<p>Note: 'postdata' can be a simple JSON structure name, in which case the system will automatically perform a ^jsonwrite on it and send that text data as the data. Currently limited to 500K in size of the internal buffer.</p>
<p>A sample call might be:</p>
<pre><code>$$url = "https://api.github.com/users/test/repos"
$$user_agent = ^"User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"
^jsonopen(GET $$url "" $$user_agent)</code></pre>
<p>where GitHub requires user-agent data. Use <code>http://</code> and <code>https://</code> in front of your urls.</p>
<p>As an example of a complex header value you might create neatly,</p>
<pre><code>$header = ^"Accept: application/json
~Accept-Encoding: identity,*;q=0
~Accept-Language: en-US,en;q=0.5
~Cache-Control: no-cache
~Connection: close
~Host: Chatscript
~User_Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:42.0) "</code></pre>
<p>ChatScript will make each line have a single space separator between line continuations. And JsonOpen will correctly get the header elements that do not include that spacing.</p>
<p>The results are a collection of facts representing the JSON parse tree and the value of the function is the root JSON value. The JSON elements that can be represented are arrays, objects, JSON strings, and primitives (numbers, true, false, null). JSON arrays are named <code>ja-n</code> where <code>n</code> is a unique index. JSON objects are similarly named <code>jo-n</code>.</p>
<p>Unlike JSON, which makes a distinction between primitives and strings, in ChatScript those things are all strings and are not quoted. So a JSON string like this:</p>
<pre><code>[ {"id": 1 "value": "hello"} {"id": 2 "value": "bye"} ]</code></pre>
<p>returns this value: <code>ja-1</code> and these facts. The facts have flags on them which you can use in queries. You may not have any need to use these flags, so maybe you will just ignore their existence.</p>
<table>
<thead>
<tr class="header">
<th>fact</th>
<th align="left">associated flags</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>(ja-1 0 jo-1)</td>
<td align="left">#<code>JSON_ARRAY_FACT</code> #<code>JSON_OBJECT_VALUE</code></td>
</tr>
<tr class="even">
<td>(jo-1 id 1)</td>
<td align="left">#<code>JSON_OBJECT_FACT</code> #<code>JSON_PRIMITIVE_VALUE</code></td>
</tr>
<tr class="odd">
<td>(jo-1 value hello)</td>
<td align="left">#<code>JSON_OBJECT_FACT</code> #<code>JSON_STRING_VALUE</code></td>
</tr>
<tr class="even">
<td>(ja-1 1 jo-2)</td>
<td align="left">#<code>JSON_ARRAY_FACT</code> <code>#JSON_OBJECT_VALUE</code></td>
</tr>
<tr class="odd">
<td>(jo-2 id 2)</td>
<td align="left">#<code>JSON_OBJECT_FACT</code> #<code>JSON_PRIMITIVE_VALUE</code></td>
</tr>
<tr class="even">
<td>(jo-2 value bye)</td>
<td align="left">#<code>JSON_OBJECT_FACT</code> #<code>JSON_STRING_VALUE</code></td>
</tr>
</tbody>
</table>
<p>Using queries, you could get all values of an array. Or all fields of an object. Or all JSON facts where the field is the id. You could manually write script to walk the entire tree. But more likely you will use <code>^jsonpath</code> to retrieve specific pieces of data you want. For example, you could do a query on the value returned by <code>^jsonopen</code> as subject, to find out how many array elements there are. Then use <code>^jsonpath</code> to walk each array element to retrieve a specific field buried within.</p>
<p>Note - for things like primitive null, null arrays, null strings, null objects, these are represented as "null" and the corresponding fact flag tells you the kind of value it is.</p>
<p>You can also ask CS to show those out visually using <code>^jsontree</code>.</p>
<p>Note that the facts created are all transient and disappear at the end of the volley unless you have forced them to stay via <code>permanent</code>. Forcing them to stay is generally a bad idea because it will congest your user topic data file, slowing it down or exceeding its capacity, and because those facts may then collide with new facts created by a new <code>^jsonopen</code> on a new volley. The array and object ids are cleared at each volley, so you will be reusing the same names on new unrelated facts.</p>
<p>Using the flag values, it is entirely possible to reconstruct the original JSON from the facts (if the root is an array or object because otherwise there are no facts involved), but I can't think of use cases at present where you might want to. You cannot compile CS on LINUX unless you have installed the CURL library. For Amazon machines that means doing this:</p>
<pre><code>sudo yum -y install libcurl libcurl-devel</code></pre>
<p>Or more completely, for evserver and curl, you might do:</p>
<pre><code>sudo yum -y install -y libc -devel gcc libc6 -compat libcurl libcurl-devel libstdc++ libgcc glibc make gcc-c++</code></pre>
<p>On some other machines that doesn't install library stuff and maybe you need</p>
<pre><code>sudo apt-get install libcurl3 libcurl3-gnutls libcurl4-openssl-dev</code></pre>
<p>System variables <code>%httpresponse</code> will hold the most recent http return code from calling <code>^jsonopen</code>.</p>
<p>If you call <code>^jsonopen(direct ...)</code> then the result will not be facts, but the text will be directly shipped back as the answer. Be wary of doing this if the result will be large (>30K?) since you will overflow your buffer without being checked.</p>
<p>^jsonopen automatically url-encodes headers and urls</p>
<p>Note: CS blocks until the call is complete. On a production server if you expect that the call can take serious time, you are advised to send the request in OOB to your own additional layer which returns to CS immediately. Then it makes the call and when the call completes, makes a call back to CS with the results in OOB.</p>
<h4 id="jsonopen-and-local-files"><code>JSONOpen and local files</code></h4>
<p>JSONOpen is a wrapper around the <code>Curl</code> library, so you can use as an url a local file reference like <code>file:///c:/myfile.txt</code>. The file, of course, should be a JSON text string.</p>
<h4 id="jsonopen-and-proxy-servers"><code>JSONOpen and proxy servers</code></h4>
<p>If you need JSONOpen to run thru a proxy server, these are the CS variables you need to set up: <code>$cs_proxycredentials</code> should be your login data, e.g. <code>myname:thesecret</code>. <code>$cs_proxyserver</code> is the server address, e.g., <code>http://local.example.com:1080</code>. <code>$cs_proxymethod</code> are bits listing the authorization method to use. They come from the LIBCURL so you should OR together the bits you want. Bit 1 is the most basic choice of name and password. Read- https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html</p>
<h2 id="json-out-of-band-output-data">JSON & Out-of-band output data</h2>
<p>Out-of-band data in ChatScript is signaled by the output beginning with data enclosed in <code>[]</code>. Which might be confusing, since JSON uses <code>[]</code> to denote an array. Standalone ChatScript contains a built-in handler for OOB data and if you pass it JSON at the start of output, it will swallow it and not display it (unless you turn on OOB display).</p>
<p>Similarly, std webpage interfaces connecting to ChatScript do likewise. So if you want to see this information, you should put something in the output at the start which is NOT the JSON data. Anything will do. The only time you might actually need the JSON clean at the beginning is from some special purpose application, and in that case you will write your own OOB handler anyway (or not have one).</p>
<h2 id="json-out-of-band-input-data">JSON & Out-of-band input data</h2>
<p>OOB data into ChatScript is similarly signaled by being at the start of input, with data enclosed in [], followed typically by the user's actual input. The ChatScript engine reacts specially to OOB incoming data in that it will be careful to not treat it like ordinary user chat. Tokenization is done uniquely, spell-checking, pos-tagging, parsing, named entity merging etc are all turned off and the data becomes its own sentence (the user's actual input generates more sentences to CS as input). OOB data is then processed by your script in any way you want. So one clever thing you can do is pass in JSON data within the OOB to get temporary facts into your app during a volley. Input might look like this:</p>
<pre><code>[ [ a b { "bob": 1, "suzy": 2 } ] ] What is your name?</code></pre>
<p>You can pattern match the oob section of the input as follows:</p>
<pre><code>u: ( \[ _* ) $_tmp = ^jsonparse('_0)</code></pre>
<p><code>_0</code> will contain an excess right bracket (the end of the oob message), but that won't bother <code>^jsonparse</code>.</p>
<p>Representing JSON in CS facts is more than just a bunch of subject-verb-object facts linked together.</p>
<p>The facts have typing bits on them that describe the structure and arrays have index values that must remain consistent. Therefore you should not create and alter JSON fact structures using ordinary CS fact routines like <code>^createfact</code> and <code>^delete</code>. Instead use the JSON routines provided.</p>
<h2 id="practical-examples">Practical Examples</h2>
<h3 id="objects">Objects</h3>
<p>The write routines <code>jsonwrite</code> and <code>jsontree</code> print out different views of the same data..</p>
<pre><code>u: (-testcase1) $_jsonObject = ^jsoncreate(object)
ˆjsonobjectinsert( $_jsonObject name “some name” )
ˆjsonobjectinsert( $_jsonObject phone “some number” )
ˆjsonwrite ( $_jsonObject ) \n
^jsontree ( $_jsonObject )\n</code></pre>
<p>Note in this next example how to escape a json string with ^''. This makes creating json objects from static data very intuitive and clear.</p>
<pre><code>u: (-testcase2) $_tmp = ^jsonparse( ^'{name: "Todd Kuebler", phone: "555.1212"}' )
^jsonwrite( $_tmp ) \n
^jsontree( $_tmp ) \n
name: $_tmp.name, phone: $_tmp.phone</code></pre>
<p>This example shows the . notation access of data inside a json object in chatscript. This is probably the most intuitive way of interacting with the data.</p>
<pre><code>u: (-testcase3) $_tmp = ^jsoncreate(object)
$_tmp.name = "Todd Kuebler"
$_tmp.phone = "555-1212"
^jsonwrite( $_tmp ) \n
^jsontree( $_tmp ) \n
name: $_tmp.name, phone: $_tmp.phone
</code></pre>
<h3 id="arrays-of-objects">Arrays of objects</h3>
<p>In the example below, we add two items into an array of objects and we display the formatted array:</p>
<pre><code>u: ( testcase4 )
# create a phoneBook as an array of structured items (objects)
$_phoneBook = ^jsoncreate(array)
# add first object in the array
#
$_item = ^jsoncreate(object)
# assign values
$_item.name = "Todd Kuebler"
$_item.phone = "555-1212"
^jsonarrayinsert($_phoneBook $_item)
# add a second object in the array
#
$_item = ^jsoncreate(object)
# assign values
$_item.name = "Giorgio Robino"
$_item.phone = "111-123456789"
^jsonarrayinsert($_phoneBook $_item)
# display JSON tree
^jsontree( $_phoneBook ) \n
#
# print formatted items in the phone book
#
phone book:\n
$_i = 0
$_size = ^length($_phoneBook)
loop($_size)
{
# print out formatted item
name: $_phoneBook[$_i].name, phone: $_phoneBook[$_i].phone\n
$_i += 1
}</code></pre>
</body>
</html>