Skip to content

Commit c0177ec

Browse files
Merge pull request #45 from solyaris/master
wiki doc: added JSON Array of object example
2 parents d2c2059 + 8013a82 commit c0177ec

File tree

1 file changed

+106
-24
lines changed

1 file changed

+106
-24
lines changed

WIKI/ChatScript-Json.md

Lines changed: 106 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
> © Bruce Wilcox, [email protected] brilligunderstanding.com
44
5-
65
> Revision 1/7/2017 cs7.1
76
87

@@ -11,7 +10,7 @@
1110
JSON (JavaScript Object Notation) is an open standard format using human-readable text to transmit
1211
data objects over the web. It is a common standard largely replacing XML which is too wordy and hard
1312
to read. JSON has two datatypes that represents collections of values, the array and the object.
14-
A JSON array is a list of JSON entities separated by commas and placed within [], e.g.,
13+
A JSON array is a list of JSON entities separated by commas and placed within `[]`, e.g.,
1514
```
1615
[ A 2 [ help life] [] ]
1716
```
@@ -78,26 +77,28 @@ structure in CS, the facts will all be unique.
7877

7978
Routines that will create facts for JSON will by default create them as transients (they die at end of
8079
volley unless you work to save them). You can override this default by saying
81-
permanent or transient. This applies to `^jsonopen`, `^jsonparse`, `^jsoncreate`,
80+
`permanent` or `transient`. This applies to `^jsonopen`, `^jsonparse`, `^jsoncreate`,
8281
`^jsonobjectinsert`, `^jsonarrayinsert`, `^jsoncopy`.
8382

84-
You can also add a flag safe to `^jsonparse`, `^jsonobjectinsert`, `^jsonarraydelete`.
85-
You can also add a flag unique to `^jsonarrayinsert`.
86-
You can also add `DUPLICATE` to ^jsonobjectinsert.
83+
You can also add a flag `safe` to `^jsonparse`, `^jsonobjectinsert`, `^jsonarraydelete`.
84+
You can also add a flag `unique` to `^jsonarrayinsert`.
85+
You can also add `duplicate` to ^jsonobjectinsert.
8786

8887
When multiple flags are desired, put them into a simple string, `"DUPLICATE PERMANENT"`. Case doesn't matter.
8988

9089
When you want to add a reference to a normal factid (as is returned by ^createfact) you can add the flag `AUTODELETE`
9190

92-
You can also assign user flags by listing USER_FLAG1, thru USER_FLAG4 as a flag as well. The JSON fact will have that flag on it, which you can use in conjunction with ^query to limit what matches can be found.
91+
You can also assign user flags by listing `USER_FLAG1`, through `USER_FLAG4` as a flag as well.
92+
The JSON fact will have that flag on it, which you can use in conjunction with `^query` to limit what matches can be found.
93+
9394

9495
### `^jsonparse`( {JSONFLAGS} string )
96+
9597
`string` is a JSON text string (as might be returned from a website) and this parses into facts.
9698
It returns the name of the root node JSON composite. This name will look like this:
9799

98-
`ja-0` – a json array numbered `0`.
99-
100-
`jo-0` – a json object numbered `0`.
100+
* `ja-0` – a json array numbered `0`.
101+
* `jo-0` – a json object numbered `0`.
101102

102103
As new JSON composites are created during a volley, the numbers increase to keep them all distinct.
103104
JSON composites are all created as transient facts and will die at the end of the volley unless you do
@@ -177,7 +178,9 @@ nominally, because it is considered a single token.
177178
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 `#JSON_DIRECT_FROM_OOB` on the `$cs_token` value and if it finds OOB data that is entirely JSON, it will parse it and return something like `jo-t1` or `ja-t1` in its place. Eg.
178179
`[ { "key": "value} ]` will return tokenized as `[jo-t1]`.
179180

180-
##jsonformat(string)`
181+
182+
## `jsonformat`(string)
183+
181184
Because technically JSON requires you put quotes around field names
182185
(though various places ignore that requirement) and because CS doesn't, the function takes in a slack
183186
json text string and outputs a strict one.
@@ -186,12 +189,14 @@ json text string and outputs a strict one.
186189
## Accessing JSON structures
187190

188191
### `^jsonpath`( string id )
189-
`string` is a description of how to walk JSON.
190-
`id` is the name of the node you want to start at (typically returned from `^jsonopen` or `^jsonparse`).
192+
193+
* `string` is a description of how to walk JSON.
194+
* `id` is the name of the node you want to start at (typically returned from `^jsonopen` or `^jsonparse`).
191195

192196
Array values are accessed using typical array notation like `[3]` and object fields using dotted notation.
193197
A simple path access might look like this: `[1].id` which means take the root object passed as id,
194198
e.g., `ja-1`, get the 2nd index value (arrays are 0-based in JSON).
199+
195200
That value is expected to be an object, so return the value corresponding to the id field of that object.
196201
In more complex situations, the value of id might itself be an object or an array,
197202
which you could continue indexing like `[1].id.firstname`.
@@ -227,7 +232,8 @@ if you add a 3rd argument "safe" to the call.
227232
```
228233

229234
### `^jsonpath`
230-
can also return the actual factid of the match, instead of the object of the fact. This would
235+
236+
Can also return the actual factid of the match, instead of the object of the fact. This would
231237
allow you to see the index of a found array element, or the json object/array name involved. Or you
232238
could use ^revisefact to change the specific value of that fact (not creating a new fact). Just add * after
233239
your final path, eg
@@ -259,6 +265,7 @@ You may omit the leading . of a path and CS will by default assume it
259265
If a variable holds a JSON object value, you can directly set and get from fields of that object
260266
using dotted notation. This can be a fixed static fieldname you give or a variable value:
261267
`$myvar.$myfield` is legal.
268+
262269
Dotted notation is cleaner and faster than `^jsonpath` and `jsonobjectinsert` and for get, has
263270
the advantage that it never fails, it only returns null if it can't find the field.
264271
On the other hand, assignment fails if the path does not contain a json object at some level.
@@ -329,23 +336,28 @@ number restricts how deep it displays. 0 (default) means all. 1 is just top leve
329336
You can build up a JSON structure without using `^jsonparse` if you want to build it piece by piece.
330337
And you can edit existing structures.
331338

339+
332340
### `^jsoncreate`( {JSONFLAGS} type )
341+
333342
Type is either array or object and a json composite with no content is created and its name returned.
334343
See `^jsonarrayinsert`, `^jsonobjectinsert`, and `^jsondelete` for how to manipulate it.
335344
See writeup earlier about optional json flags.
336345

346+
337347
### `^jsonarrayinsert`( {JSONFLAGS} arrayname value )
348+
338349
Given the name of a json array and a value, it adds the value to the end of the array.
339350
See writeup earlier about optional json flags.
340351
If you use the flag unique then if value already exists in the array, no duplicate will be added.
341352

342-
### `^jsonarraydelete`( [INDEX, VALUE] arrayname value )
353+
354+
### `^jsonarraydelete`( [`INDEX`, `VALUE`] arrayname value )
355+
343356
This deletes a single entry from a JSON array. It does not damage the thing deleted, just its member in the array.
344-
If the first argument is INDEX, then value is a number which is the array index (0 n-1).
345-
If the first argument is VALUE, then value is the value to find and remove as the object of the json fact.
357+
* If the first argument is `INDEX`, then value is a number which is the array index (0 ... n-1).
358+
* If the first argument is `VALUE`, then value is the value to find and remove as the object of the json fact.
346359

347-
You can delete every matching `VALUE` entry by adding the optional argument `ALL`. Like:
348-
`^jsonarraydelete("INDEX ALL" $array 4)`
360+
You can delete every matching `VALUE` entry by adding the optional argument `ALL`. Like: `^jsonarraydelete("INDEX ALL" $array 4)`
349361

350362
If there are numbered elements after this one, then those elements immediately renumber downwards
351363
so that the array indexing range is contiguous.
@@ -356,12 +368,17 @@ suppress this with the `SAFE` flag. `^jsonarraydelete(SAFE $obj $key)`.
356368

357369

358370
### `^jsonarraysize`( name )
371+
359372
deprecated in favor of ^length
360373

374+
361375
### `^jsoncopy`( name )
376+
362377
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.
363378

379+
364380
### `^jsonobjectinsert`( {JSONFLAGS} objectname key value )
381+
365382
inserts the key value pair into the object named. The key does not require quoting.
366383
Inserting a json string as value requires a quoted string.
367384
Duplicate keys are ignored unless the optional 1st argument `DUPLICATE` is given.
@@ -371,30 +388,40 @@ If the key has an existing value and `DUPLICATE` is not a factor, then if the va
371388
recursively deleted provided its data is not referenced by some other fact (not by any variables). You can
372389
suppress this with the `SAFE` flag. `jsonobjectinsert(SAFE $obj $key null)`.
373390

391+
374392
### `^jsondelete`( factid )
393+
375394
deprecated in favor of ^delete
376395

396+
377397
### `^jsongather`( {fact-set} jsonid {level})
398+
378399
takes the facts involved in the json data (as returned by `^jsonparse` or `^jsonopen`)
379-
and stores them in the named factset.
400+
and stores them in the named factset.
380401
This allows you to remove their transient flags or save them in the users permanent data file.
381402

382403
You can omit fact-set as an argument if you are using an assignment statement:
383-
`@1 = ^jsongather(jsonid)'
404+
`@1 = ^jsongather(jsonid)`
384405

385406
`^Jsongather` normally gathers all levels of the data recursively. You can limit how far down it goes by
386407
supplying `level`. Level 0 is all. Level 1 is the top level of data. Etc.
387408

409+
388410
### `^jsonlabel`( label )
411+
389412
assigns a text sequence to add to jo- and ja- items created thereafter. See System functions manual.
390413

414+
391415
### `^jsonundecodestring`( string )
416+
392417
removes all json escape markers back to normal for possible printout
393418
to a user. This translates \\n to newline, \\r to carriage return, \\t to tab, and \\" to a simple quote.
394419

420+
395421
## WEB JSON
396422

397423
### `^jsonopen`( {JSONFLAGS} kind url postdata header {timeout})
424+
398425
this function queries a website and returns a JSON datastructure as facts.
399426
It uses the standard CURL library, so it's arguments and how to use them are
400427
generally defined by CURL documentation and the website you intend to access.
@@ -459,7 +486,8 @@ the field is the id. You could manually write script to walk the entire tree. Bu
459486
`^jsonpath` to retrieve specific pieces of data you want. For example, you could do a query on the
460487
value returned by `^jsonopen` as subject, to find out how many array elements there are. Then use
461488
`^jsonpath` to walk each array element to retrieve a specific field buried within.
462-
Note- for things like primitive null, null arrays, null strings, null objects, these are represented as "null"
489+
490+
Note - for things like primitive null, null arrays, null strings, null objects, these are represented as "null"
463491
and the corresponding fact flag tells you the kind of value it is.
464492

465493
You can also ask CS to show those out visually using `^jsontree`.
@@ -490,6 +518,7 @@ If you call `^jsonopen(direct ...` then the result will not be facts, but the te
490518
back as the answer. Be wary of doing this if the result will be large (>30K?) since you will overflow your
491519
buffer without being checked.
492520

521+
493522
## JSON & Out-of-band output data
494523

495524
Out-of-band data in ChatScript is signaled by the output beginning with data enclosed in `[]`.
@@ -529,6 +558,7 @@ fact routines like `^createfact` and `^delete`. Instead use the JSON routines pr
529558

530559
## Practical Examples
531560

561+
### Objects
532562
The write jsonwrite and json tree print out different views of the same data..
533563

534564
u: (-testcase1) $$jsonObject = ^jsoncreate(object)
@@ -544,11 +574,63 @@ Note in this next example how to escpe a json string with ^''. This makes creat
544574
^jsontree( $$tmp ) \n
545575
name: $$tmp.name, phone: $$tmp.phone
546576

547-
This example shows the . notation access of data inside an json object in chatscript. This is probably the most intuitive way of interacting with the data.
577+
This example shows the . notation access of data inside an json object in chatscript. This is probably the most intuitive way of interacting with the data.
548578

549579
u: (-testcase3) $$tmp = ^jsoncreate(object)
550580
$$tmp.name = "Todd Kuebler"
551581
$$tmp.phone = "555-1212"
552582
^jsonwrite( $$tmp ) \n
553583
^jsontree( $$tmp ) \n
554-
name: $$tmp.name, phone: $$tmp.phone
584+
name: $$tmp.name, phone: $$tmp.phone
585+
586+
587+
### Arrays of objects
588+
589+
In the example below, we add two items into an array of objects and we display the formatted array:
590+
591+
```
592+
u: ( testcase4 )
593+
# create a phoneBook as an array of structured items (objects)
594+
$$phoneBook = ^jsoncreate(array)
595+
596+
#
597+
# add first object in the array
598+
#
599+
$$item = ^jsoncreate(object)
600+
601+
# assign values
602+
$$item.name = "Todd Kuebler"
603+
$$item.phone = "555-1212"
604+
605+
^jsonarrayinsert($$phoneBook $$item)
606+
607+
#
608+
# add a second object in the array
609+
#
610+
$$item = ^jsoncreate(object)
611+
612+
# assign values
613+
$$item.name = "Giorgio Robino"
614+
$$item.phone = "111-123456789"
615+
616+
^jsonarrayinsert($$phoneBook $$item)
617+
618+
# display JSON tree
619+
^jsontree( $$phoneBook ) \n
620+
621+
#
622+
# print formatted items in the phone book
623+
#
624+
phone book:\n
625+
$$i = 0
626+
loop()
627+
{
628+
# print out formatted item
629+
name: $$phoneBook[$$i].name, phone: $$phoneBook[$$i].phone\n
630+
631+
$$i += 1
632+
$$size = ^length($$phoneBook)
633+
if ( $$i == $$size ) { end( loop ) }
634+
}
635+
```
636+

0 commit comments

Comments
 (0)