Load, Dump and Manipulate JSON in Bash
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.pkg
bin
doc
ext/test-more-bash
lib
man/man1
note
test
.travis.yml
Changes
License
Makefile
Meta
ReadMe.pod

ReadMe.pod

Name

JSON - JSON for Bash

json-bash

Synopsis

source json.bash

json='{"name":"Jason","friends":["Jimmy","Joe"]}'
JSON.load "$json"
joe=$(JSON.get /friends/1)
JSON.put /friends/2 Jeff
new_json=$(JSON.dump)

Description

The json.bash library provides functions for loading, manipulating and dumping JSON data.

Bash doesn't have nestable hashes and arrays to load JSON data into. This library provides a different data model called a "linear tree". A linear tree is simply a sequence of text lines, each containing a key-path and a leaf- value (separated by a tab):

/key/path<HARD-TAB>"leaf value"

Thus this JSON:

{
  "name": {
    "first": "Jimmy",
    "last": "James"
  },
  "list": [
    "A string",
    42,
    [ true, false, null ]
  ]
}

Would be loaded as this linear tree:

/name/first     "Jimmy"
/name/last      "James"
/list/0 "A string"
/list/1 42
/list/2/0       true
/list/2/1       false
/list/2/2       null

Since Bash has many tools for searching and manipulating text, the linear form works fairly well for common JSON data operations.

Installation

Just run:

make install

This may require sudo permission.

By default, this will install:

/usr/local/lib/bash/test-simple.bash
/usr/local/share/man/man1/test-simple.1

You can change the install locations with these environment variables:

  • PREFIX - default is /usr/local

  • INSTALL_LIB

  • INSTALL_MAN

Run make help to see all the make targets that are available.

API Functions

The library contains functions to load JSON to the linear form and to dump that form back into JSON. It also has functions to retrieve, modify, add and remove data from the linear form.

JSON.load [ <json-string> [<linear-var-name>]]

This function takes JSON as input and generates a linear tree as output.

With no arguments, input is read from stdin and output is written to stdout. With one argument, the input is provided as a string argument and the output is stored in an internal cache variable. With two arguments the input is again provided as a string argument, and the output is copied into the variable name provided.

JSON.dump [<linear-var-name>]

This function takes a linear tree as input and generates JSON as output.

With no arguments, input is read from stdin. With one argument, input is taken from the provided variable name. To use the internal cache, use - as the variable name. Output is always written to stdout.

JSON.get [-a|-s|-b|-n|-z] <key-path> [<linear-var-name>]

This function takes a key path and returns the corresponding value. If the key is found, the exit status is 0, otherwise it is 1. If the value is a string, it will be enclosed in double quotes. Otherwise it will be a number or the unquoted strings: true, false or null.

With just the one required argument, the linear tree will be obtained from stdin. Otherwise it can be provided with a variable name (or - for the cache). The value (if any) is written to stdout.

See FLAGS below for an explanation of the flag options.

JSON.keys <key-path> [<linear-var-name>]

This function takes a key path and returns the keys of the corresponding object, one per line. If the key is not found or the value of the key is not an object, it will return nothing.

JSON.object <key-path> [<linear-var-name>]

This function takes a key path and returns the corresponding object. If the key is not found, it will return nothing.

JSON.put [-s|-b|-n|-z] <key-path> <new-value> [<linear-var-name>]

This function adds a path/value pair to the linear tree. If the path already exists, the value will be replaced, otherwise it will be added.

With just the two required arguments, the linear tree will be obtained from stdin. Otherwise it can be provided with a variable name (or - for the cache). Nothing will be written to stdout and the exit status will always be 0.

JSON.del <key-path> <new-value> [<linear-var-name>]

This function removes a path/value pair from the linear tree, if it exists.

With just the one required argument, the linear tree will be obtained from stdin. Otherwise it can be provided with a variable name (or - for the cache). Nothing will be written to stdout and the exit status will always be 0.

Heuristics will be used to determine what type the value is. The -s flag indicates the value is a string, the -n flag indicates a number,the -b flag indicates a boolean and the -z flag indicates a null value.

JSON.cache [<linear-var-name>]

Outputs the value of the internal linear tree cache string.

With no arguments, the value is written to stdout. With one argument, the value is copied to the variable name provided.

Flags

The command flags -a, -s, -n, -b and -z indicate the type of value provided or expected, and they refer to Any, String, Number, Boolean and Null respectively. If the type of data doesn't look like the type indicated by the flag, the command will return with a status code of 2.

If -a is used, the double quotes at each end (if any) will be removed for a JSON.get.

If -s is used and the data is a string, the double quotes will be removed for a JSON.get or added for a JSON.put.

The -n flag requires no value transformation, but it will cause the command to fail (status 2) if the value is not a number.

If -b is used for a JSON.get, true will become 0 and false will become 1. JSON.put will do the reverse. This follows Bash's idea of using 0 for a successful return code.

The -z flag on a JSON.get will turn null into the empty string, and for a JSON.put will turn any value into null.

Examples

# Load JSON to linear tree
JSON.load "$(< file.json)" tree
# or:
tree=$(cat file.json | JSON.load)

# Get a value
first_name=$(JSON.get /name/first tree)
# or:
first_name=$(echo "$tree" | JSON.get /name/first)

# Change a value
JSON.put /name/first Jimmy tree
# or:
tree=(echo "$tree" | JSON.put /name/first Jimmy)

# Delete a value
JSON.del /name/middle tree
# or:
tree=(echo "$tree" | JSON.del /name/middle)

# Dump a linear tree to JSON
JSON.dump tree > new-file.json
# or:
echo "$tree" | JSON.dump > new-file.json

Problems

This library is meant to be useful for solving common problems involving JSON. However, without the native JSON object model in Bash, it becomes problematic the further you stray from the norm.

Here is a list of known issues. Some may be addressed, some are very likely to stay out of scope:

  • No support for empty arrays and empty objects.

  • No support for key-paths that refer to objects or arrays.

  • No support for common array operations like push, pop, splice, etc.

Todo

  • Support object keys that:

    • Contain whitespace

    • Consist of all digit characters

    • Contain backslashes

  • Implement JSON.dump

Status

Please report any issues to https://github.com/ingydotnet/json-bash/issues

Or find me on ingy@irc.freenode.net.

Author

Written by Ingy döt Net <ingy@ingy.net>

Copyright & License

Copyright 2013-2016 Ingy döt Net

The MIT License (MIT)