| 1 | ---
 | 
| 2 | default_highlighter: oils-sh
 | 
| 3 | ---
 | 
| 4 | 
 | 
| 5 | JSON in Oils
 | 
| 6 | ===========
 | 
| 7 | 
 | 
| 8 | [JSON](https://www.json.org/) is used by both web services and command line
 | 
| 9 | tools, so a modern Unix shell needs to support it.
 | 
| 10 | 
 | 
| 11 | Oils has a `json` builtin which you can use from bot OSH and YSH.
 | 
| 12 | 
 | 
| 13 | It also has a parallel `json8` builtin with the same uage.  See [J8
 | 
| 14 | Notation](j8-notation.html) for details on the encoding.
 | 
| 15 | 
 | 
| 16 | <div id="toc">
 | 
| 17 | </div>
 | 
| 18 | 
 | 
| 19 | The `json` **builtin** has `read` and `write` subcommands, which convert
 | 
| 20 | between serialized data languages and in-memory data structures.
 | 
| 21 | 
 | 
| 22 | YSH data structures are like those in Python and JavaScript, so this
 | 
| 23 | correspondence is natural.
 | 
| 24 | 
 | 
| 25 | ## `json read` parses from `stdin`
 | 
| 26 | 
 | 
| 27 | Usage:
 | 
| 28 | 
 | 
| 29 |     json  read (PLACE?)
 | 
| 30 |     json8 read (PLACE?)
 | 
| 31 | 
 | 
| 32 | Examples:
 | 
| 33 | 
 | 
| 34 |     $ cat stats.json
 | 
| 35 |     {"count": 42}
 | 
| 36 | 
 | 
| 37 |     # Read from a file.  By default, the variable _reply is written.
 | 
| 38 |     $ json read < stats.json
 | 
| 39 | 
 | 
| 40 |     # Use = to pretty print an expression
 | 
| 41 |     $ = _reply
 | 
| 42 |     (Dict)   {'count': 42}
 | 
| 43 | 
 | 
| 44 | Specify a place to put the data:
 | 
| 45 | 
 | 
| 46 |     $ json read (&myvar) < stats.json
 | 
| 47 | 
 | 
| 48 |     $ = myvar
 | 
| 49 |     (Dict)   {'count': 42}
 | 
| 50 | 
 | 
| 51 | Use it in a pipeline:
 | 
| 52 | 
 | 
| 53 |     # 'json read' is valid at the end of a pipeline (because YSH implements
 | 
| 54 |     # shopt -s lastpipe)
 | 
| 55 |     $ echo '{"count": 42}' | json read (&myvar)
 | 
| 56 | 
 | 
| 57 | Failure with invalid input data:
 | 
| 58 | 
 | 
| 59 |     $ echo '[ "incomplete"' | json read (&myvar) < invalid.json
 | 
| 60 |     [ "incomplete"
 | 
| 61 |      ^
 | 
| 62 |     json read: premature EOF
 | 
| 63 | 
 | 
| 64 |     $ echo $?
 | 
| 65 |     1
 | 
| 66 | 
 | 
| 67 | ## `json write` prints to `stdout`
 | 
| 68 | 
 | 
| 69 | Usage:
 | 
| 70 | 
 | 
| 71 |     json write (EXPR, space=2)
 | 
| 72 |     
 | 
| 73 |     EXPR is an expression that evaluates to a serializable object.
 | 
| 74 | 
 | 
| 75 |     space is the number of spaces that object and array entries are indented
 | 
| 76 |     by.  If it's 0 or less, then no newlines or spaces are printed.
 | 
| 77 | 
 | 
| 78 | Examples:
 | 
| 79 | 
 | 
| 80 |     $ var d = {name: "bob", age: 42}  # create Dict
 | 
| 81 | 
 | 
| 82 |     $ json write (d)  # print as JSON, with 2 space indent
 | 
| 83 |     {
 | 
| 84 |       "name": "bob",
 | 
| 85 |       "count": 42
 | 
| 86 |     }
 | 
| 87 | 
 | 
| 88 |     $ json write (d, space=0)  # no indent at all
 | 
| 89 |     {"name":"bob","count":42}
 | 
| 90 | 
 | 
| 91 | ### `write` builtin
 | 
| 92 | 
 | 
| 93 | TODO
 | 
| 94 | 
 | 
| 95 |     write --j8 hello there
 | 
| 96 |     write --json hello there  # unicode replacement char
 | 
| 97 | 
 | 
| 98 | ## Filter Data Structures with YSH Expressions
 | 
| 99 | 
 | 
| 100 | Once your data is deserialized, you can use YSH expression to operate on it.
 | 
| 101 | 
 | 
| 102 |     $ echo '{"counts": [42, 99]}' | json read (&d)
 | 
| 103 | 
 | 
| 104 |     $ = d['counts']
 | 
| 105 |     (List)   [42, 99]
 | 
| 106 | 
 | 
| 107 |     $ = d['counts'][1]
 | 
| 108 |     (Int)    99
 | 
| 109 | 
 | 
| 110 |     # d->counts is a synonym for d["counts"]
 | 
| 111 |     $ json write (d->counts)
 | 
| 112 |     [
 | 
| 113 |       42,
 | 
| 114 |       99
 | 
| 115 |     ]
 | 
| 116 | 
 | 
| 117 | Note: It may more efficient to filter large data structures with tools like
 | 
| 118 | `jq` first.
 | 
| 119 | 
 | 
| 120 | ## Other Data Structures Can Be Printed as JSON
 | 
| 121 | 
 | 
| 122 | YSH arrays and shell arrays both serialize to a list of strings:
 | 
| 123 | 
 | 
| 124 |     $ declare sharray=( foo.txt *.py )
 | 
| 125 |     $ json write (sharray)
 | 
| 126 |     [  
 | 
| 127 |        "foo.txt",
 | 
| 128 |        "one.py",
 | 
| 129 |        "two.py"
 | 
| 130 |     ]
 | 
| 131 | 
 | 
| 132 |     $ var oilarray = :| foo.txt *.py |
 | 
| 133 |     $ json write (oilarray)
 | 
| 134 |     [  
 | 
| 135 |        "foo.txt",
 | 
| 136 |        "one.py",
 | 
| 137 |        "two.py"
 | 
| 138 |     ]
 | 
| 139 | 
 | 
| 140 | Bash-style associative arrays are printed like `Dict[Str, Str]`:
 | 
| 141 | 
 | 
| 142 |     $ declare -A assoc=(["key"]=value)
 | 
| 143 |     $ json write (assoc)
 | 
| 144 |     {
 | 
| 145 |       "key": "value"
 | 
| 146 |     }
 | 
| 147 | 
 |