-
Notifications
You must be signed in to change notification settings - Fork 154
Expand file tree
/
Copy pathChatScript-Json.html
More file actions
1303 lines (1290 loc) · 66.5 KB
/
ChatScript-Json.html
File metadata and controls
1303 lines (1290 loc) · 66.5 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
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>ChatScript-Json</title>
<style>
html {
color: #1a1a1a;
background-color: #fdfdfd;
}
body {
margin: 0 auto;
max-width: 36em;
padding-left: 50px;
padding-right: 50px;
padding-top: 50px;
padding-bottom: 50px;
hyphens: auto;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 12px;
}
h1 {
font-size: 1.8em;
}
}
@media print {
html {
background-color: white;
}
body {
background-color: transparent;
color: black;
font-size: 12pt;
}
p, h2, h3 {
orphans: 3;
widows: 3;
}
h2, h3, h4 {
page-break-after: avoid;
}
}
p {
margin: 1em 0;
}
a {
color: #1a1a1a;
}
a:visited {
color: #1a1a1a;
}
img {
max-width: 100%;
}
svg {
height; auto;
max-width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 1.4em;
}
h5, h6 {
font-size: 1em;
font-style: italic;
}
h6 {
font-weight: normal;
}
ol, ul {
padding-left: 1.7em;
margin-top: 1em;
}
li > ol, li > ul {
margin-top: 0;
}
blockquote {
margin: 1em 0 1em 1.7em;
padding-left: 1em;
border-left: 2px solid #e6e6e6;
color: #606060;
}
code {
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
font-size: 85%;
margin: 0;
hyphens: manual;
}
pre {
margin: 1em 0;
overflow: auto;
}
pre code {
padding: 0;
overflow: visible;
overflow-wrap: normal;
}
.sourceCode {
background-color: transparent;
overflow: visible;
}
hr {
background-color: #1a1a1a;
border: none;
height: 1px;
margin: 1em 0;
}
table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
overflow-x: auto;
display: block;
font-variant-numeric: lining-nums tabular-nums;
}
table caption {
margin-bottom: 0.75em;
}
tbody {
margin-top: 0.5em;
border-top: 1px solid #1a1a1a;
border-bottom: 1px solid #1a1a1a;
}
th {
border-top: 1px solid #1a1a1a;
padding: 0.25em 0.5em 0.25em 0.5em;
}
td {
padding: 0.125em 0.5em 0.25em 0.5em;
}
header {
margin-bottom: 4em;
text-align: center;
}
#TOC li {
list-style: none;
}
#TOC ul {
padding-left: 1.3em;
}
#TOC > ul {
padding-left: 0;
}
#TOC a:not(:hover) {
text-decoration: none;
}
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
/* The extra [class] is a hack that increases specificity enough to
override a similar rule in reveal.js */
ul.task-list[class]{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
/* CSS for syntax highlighting */
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { color: #008000; } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { color: #008000; font-weight: bold; } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="chatscript-json-manual">ChatScript JSON Manual</h1>
<p>© Bruce Wilcox, mailto:gowilcox@gmail.com
www.brilligunderstanding.com <br>Revision 6/13/2022 cs13.2</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).</p>
<p>If you have an array, you can use dot notation to find the index of
some value in it, eg</p>
<pre><code> $_index = $array.space</code></pre>
<p>will find what array index the value <code>space</code> is at;</p>
<ol start="15" type="1">
<li>given an jsonarray treated as an object (using dot) $array.value
returns the index of the element that has that value</li>
</ol>
<p>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" id="cb4"><pre
class="sourceCode json"><code class="sourceCode json"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span> </span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="dt">"key1"</span><span class="fu">:</span> <span class="dv">1</span><span class="fu">,</span> </span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">"bob"</span><span class="fu">:</span> <span class="st">"help"</span><span class="fu">,</span> </span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">"1"</span><span class="fu">:</span> <span class="dv">7</span><span class="fu">,</span> </span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a> <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>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">"object12"</span><span class="fu">:</span> <span class="fu">{}</span> </span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></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" id="cb5"><pre
class="sourceCode json"><code class="sourceCode json"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> <span class="dt">"firstName"</span><span class="fu">:</span> <span class="st">"John"</span><span class="fu">,</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">"lastName"</span><span class="fu">:</span> <span class="st">"Smith"</span><span class="fu">,</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">"age"</span><span class="fu">:</span> <span class="dv">25</span><span class="fu">,</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">"address"</span><span class="fu">:</span> <span class="fu">{</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">"streetAddress"</span><span class="fu">:</span> <span class="st">"21 2nd Street"</span><span class="fu">,</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">"city"</span><span class="fu">:</span> <span class="st">"New York"</span><span class="fu">,</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a> <span class="dt">"state"</span><span class="fu">:</span> <span class="st">"NY"</span><span class="fu">,</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">"postalCode"</span><span class="fu">:</span> <span class="st">"10021-3100"</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a> <span class="fu">},</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a> <span class="dt">"phoneNumbers"</span><span class="fu">:</span> <span class="ot">[</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a> <span class="fu">{</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a> <span class="dt">"type"</span><span class="fu">:</span> <span class="st">"home"</span><span class="fu">,</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a> <span class="dt">"number"</span><span class="fu">:</span> <span class="st">"212 555-1234"</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a> <span class="fu">}</span><span class="ot">,</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a> <span class="fu">{</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a> <span class="dt">"type"</span><span class="fu">:</span> <span class="st">"office"</span><span class="fu">,</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a> <span class="dt">"number"</span><span class="fu">:</span> <span class="st">"646 555-4567"</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a> <span class="fu">}</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a> <span class="ot">]</span><span class="fu">,</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a> <span class="dt">"children"</span><span class="fu">:</span> <span class="ot">[]</span><span class="fu">,</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a> <span class="dt">"spouse"</span><span class="fu">:</span> <span class="kw">null</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></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>
<p>Note, also, that while JSON is case sensitive in its field names, CS
will lookup insensitive. It doesn’t matter if you mis-capitalize the
name of a field. CS doesn’t believe you should have two fields with the
same name but different capitalization and will treat them as the
same.</p>
<p>JSON is case sensitive in field names. CS is not. If you offer a new
case field name and it already has a field with a different case, it
will use the preexisting one.</p>
<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-ignoreconcept-underscoreconcept"><code>^jsonparse</code>(
{JSONFLAGS} string {~ignoreconcept { ~underscoreconcept} })</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>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>Note: You cannot normally 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>But you can pass JSON data directly as part of user input with
warning. 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 (regardless of
the setting of tokencontrol). 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>
<p>If you have given an ignoreconcept, then whenver a field name is
encountered in the incoming data matches the name of a member of that
concept set, that field and all data below it are discarded and not
returned.</p>
<p>If you have given an underscore concept, then any field name
encountered in the incoming data that matches a member of that concept,
that field’s string value will have any spaces in it replaced with
underscores.’</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>HOWEVER, if you have explicitly created an array using ^jsoncreate,
it will add elements based on how you declared it (UNIQUE or
DUPLICATE)</p>
<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> If a variable has as its value the name of
another variable, CS will attempt to autoindirect through it to get to
the JSON structure. if <span class="math inline"><em>x</em> = ′</span>y’
and $y points to a json structure, then $x is indirected and $x.val
means $y.val .</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>
<p>The system makes ids with different names for build0, build1, and
user. And increments ids as it creates new ones. If the id created
already exists, the system increments and tries again. If there are lots
of collisions you can speed things up by setting $cs_jid. This changes
the number to start with.</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="jsonreusekill-jsonstruct"><code>^jsonreusekill</code>(
$jsonstruct )</h3>
<p>Kills the facts of this struct and makes them immediately available
for reuse as free facts.</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-filepathfn"><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>
<p>An input line can be :trace all or :trace none to observe behavior of
the data between them.</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-ignoreconcept-underscoreconcept-timeout"><code>^jsonopen</code>(
{JSONFLAGS} kind url postdata header {ignoreconcept {underscoreconcept}
} {timeout})</h3>