Skip to content

Instantly share code, notes, and snippets.

@jdp
Last active August 29, 2015 14:09
Show Gist options
  • Save jdp/cc44dc598d9c2feed5a8 to your computer and use it in GitHub Desktop.
Save jdp/cc44dc598d9c2feed5a8 to your computer and use it in GitHub Desktop.
JSON shorthand for your CLI
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
import os
import sys
class InvalidJSONError(ValueError):
def __init__(self, key, *args, **kwargs):
self.key = key
super(InvalidJSONError, self).__init__(key, *args, **kwargs)
def makepair(pair):
"""Return a (key, value) tuple from a KEY=VALUE formatted string.
Most of the time, both the key and value are strings.
>>> makepair("foo=bar")
('foo', 'bar')
But integers and floats are recognized too.
>>> makepair("foo=42")
('foo', 42)
>>> makepair("foo=4.20")
('foo', 4.2)
You can force values to be strings by surrounding them with double quotes.
>>> makepair('foo="69"')
('foo', '69')
Pairs without an = delimiter have the value None.
>>> makepair("foo")
('foo', None)
If you need to insert raw JSON values, you can do it with KEY:=VALUE format.
>>> makepair("foo:=[1, 2, 3]")
('foo', [1, 2, 3])
"""
parts = pair.split('=', 1)
if len(parts) == 1:
parts.append(None)
key, value = parts
if key[-1] == ":":
key = key[:-1]
try:
value = json.loads(value)
except ValueError:
raise InvalidJSONError(key)
elif value is not None:
try:
value = int(value)
except ValueError:
try:
value = float(value)
except ValueError:
if len(value) >= 2 and value[0] == '"' and value[-1] == '"':
value = value[1:-1]
return key, value
def fatal(msg, code=1):
sys.stderr.write("{}: {}\n".format(os.path.basename(sys.argv[0]), msg))
sys.exit(code)
def main():
try:
result = dict(makepair(pair) for pair in sys.argv[1:])
sys.stdout.write(json.dumps(result))
except InvalidJSONError as e:
fatal("valid JSON value required for key `{}'".format(e.key))
if __name__ == '__main__':
main()
@jdp
Copy link
Author

jdp commented Nov 18, 2014

jarg just converts KEY=VALUE pairs from its arguments and formats them as a JSON object.

$ jarg issue=15 head=smparkes:synchrony base=master
{"head": "smparkes:synchrony", "base": "master", "issue": 15}

It can make invoking curl much nicer, and things easier wherever you find yourself writing out JSON into your shell.

$ curl http://requestb.in/oppqwtop -d "$(jarg issue=15 head=smparkes:synchrony base=master)"
ok

@jdp
Copy link
Author

jdp commented Nov 18, 2014

With cURL doing the HTTP plumbing, jarg handling the shorthand JSON syntax, and jq doing the syntax highlighting, you can quickly get a poor man's HTTPie with a tiny shell function:

function httpie2() {
  local method="$1";
  local url="$2";
  shift 2;
  curl -X"$method" "$url" -H"Content-Type: application/json" -d "$(jarg $*)" | jq .
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment