JSON in Oil

JSON is used by both web services and command line tools, so a modern Unix shell needs support for it.

Table of Contents
json read parses from stdin
json write prints to stdout
Filter Data Structures with Oil Expressions
Other Data Structures Can Be Printed as JSON
Credits

The json builtin has read and write subcommands, which convert between text and data structures in memory. Oil's data structures are like those in Python and JavaScript, so this correspondence is natural.

json read parses from stdin

Usage:

json read FLAGS* VAR_NAME

Flags:
  None for now, but there likely will be one to skip UTF-8 validation.

Examples:

$ cat stats.json
{"count": 42}

# Read from a file.  myvar is created in local scope.
$ json read :myvar < stats.json

# Use = to pretty print an expression
$ = myvar   
(Dict)   {'count': 42}

# 'json read' is valid at the end of a pipeline (because Oil implements
# shopt -s lastpipe)
$ echo '{"count": 42}' | json read :myvar

# Failure with invalid input data
$ echo '[ "incomplete"' | json read :myvar < invalid.json
[ "incomplete"
 ^
json read: premature EOF

$ echo $?
1

Notes:

json write prints to stdout

Usage:

json write FLAGS* (EXPR)

EXPR is an expression that evaluates to a serializable object.

Flags:
  --indent=2     Indentation size
  --pretty=true  Whether to add newlines for readability

Examples:

# Create a Dict.  As in JavaScript, keys don't require quotes.
$ var d = {name: "bob", age: 42}

# Print the Dict as JSON.  By default, newlines are added for readability,
# with 2 space indentation.
$ json write (d)
{
  "name": "bob",
  "count": 42
}

$ json write --indent 4 (d)
{
    "name": "bob",
    "count": 42
}

$ json write --pretty=F (d)
{"name": "bob", "count": 42}

Notes:

Filter Data Structures with Oil Expressions

Once your data is deserialized, you can use Oil expression to operate on it.

$ echo '{"counts": [42, 99]}' | json read :d

$ = d['counts']
(List)   [42, 99]

$ = d['counts'][1]
(Int)    99

# d->counts is a synonym for d["counts"]
$ json write (d->counts)
[
  42,
  99
]

Note: It may more efficient to filter large data structures with tools like jq first.

Other Data Structures Can Be Printed as JSON

Oil arrays and shell arrays both serialize to a list of strings:

$ declare sharray=( foo.txt *.py )
$ json write (sharray)
[  
   "foo.txt",
   "one.py",
   "two.py"
]

$ var oilarray = %( foo.txt *.py )
$ json write (oilarray)
[  
   "foo.txt",
   "one.py",
   "two.py"
]

Bash-style associative arrays are printed like Dict[Str, Str]:

$ declare -A assoc=(["key"]=value)
$ json write (assoc)
{
  "key": "value"
}

Credits

Under the hood, Oil uses yajl and a fork of the py-yajl binding.


Generated on Thu May 19 20:44:26 EDT 2022