diff --git a/cliff/formatters/json_format.py b/cliff/formatters/json_format.py new file mode 100644 index 00000000..fc35da19 --- /dev/null +++ b/cliff/formatters/json_format.py @@ -0,0 +1,30 @@ +"""Output formatters for JSON. +""" + +import json + +from .base import ListFormatter, SingleFormatter + + +class JSONFormatter(ListFormatter, SingleFormatter): + + def add_argument_group(self, parser): + group = parser.add_argument_group(title='json formatter') + group.add_argument( + '--noindent', + action='store_true', + dest='noindent', + help='whether to disable indenting the JSON' + ) + + def emit_list(self, column_names, data, stdout, parsed_args): + items = [] + for item in data: + items.append(dict(zip(column_names, item))) + indent = None if parsed_args.noindent else 2 + json.dump(items, stdout, indent=indent) + + def emit_one(self, column_names, data, stdout, parsed_args): + one = dict(zip(column_names, data)) + indent = None if parsed_args.noindent else 2 + json.dump(one, stdout, indent=indent) diff --git a/cliff/tests/test_formatters_json.py b/cliff/tests/test_formatters_json.py new file mode 100644 index 00000000..26d6f5e1 --- /dev/null +++ b/cliff/tests/test_formatters_json.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +from six import StringIO +import json + +from cliff.formatters import json_format + +import mock + + +def test_json_format_one(): + sf = json_format.JSONFormatter() + c = ('a', 'b', 'c', 'd') + d = ('A', 'B', 'C', '"escape me"') + expected = { + 'a': 'A', + 'b': 'B', + 'c': 'C', + 'd': '"escape me"' + } + args = mock.Mock() + sf.add_argument_group(args) + + args.noindent = True + output = StringIO() + sf.emit_one(c, d, output, args) + value = output.getvalue() + print(len(value.splitlines())) + assert 1 == len(value.splitlines()) + actual = json.loads(value) + assert expected == actual + + args.noindent = False + output = StringIO() + sf.emit_one(c, d, output, args) + value = output.getvalue() + assert 6 == len(value.splitlines()) + actual = json.loads(value) + assert expected == actual + + +def test_json_format_list(): + sf = json_format.JSONFormatter() + c = ('a', 'b', 'c') + d = ( + ('A1', 'B1', 'C1'), + ('A2', 'B2', 'C2'), + ('A3', 'B3', 'C3') + ) + expected = [ + {'a': 'A1', 'b': 'B1', 'c': 'C1'}, + {'a': 'A2', 'b': 'B2', 'c': 'C2'}, + {'a': 'A3', 'b': 'B3', 'c': 'C3'} + ] + args = mock.Mock() + sf.add_argument_group(args) + + args.noindent = True + output = StringIO() + sf.emit_list(c, d, output, args) + value = output.getvalue() + assert 1 == len(value.splitlines()) + actual = json.loads(value) + assert expected == actual + + args.noindent = False + output = StringIO() + sf.emit_list(c, d, output, args) + value = output.getvalue() + assert 17 == len(value.splitlines()) + actual = json.loads(value) + assert expected == actual diff --git a/doc/source/list_commands.rst b/doc/source/list_commands.rst index b49c651a..d682ff92 100644 --- a/doc/source/list_commands.rst +++ b/doc/source/list_commands.rst @@ -114,11 +114,35 @@ mappings. - Name: cliffdemo Size: 4096 +json +---- + +The ``json`` formatter produces an array of objects in indented JSON +format. + +:: + + (.venv)$ cliffdemo files -f json + [ + { + "Name": "source", + "Size": 4096 + }, + { + "Name": "Makefile", + "Size": 5569 + }, + { + "Name": "build", + "Size": 4096 + } + ] + Other Formatters ---------------- -Formatters using tablib_ to produce JSON and HTML are available -as part of `cliff-tablib`_. +A formatter using tablib_ to produce HTML is available as part of +`cliff-tablib`_. .. _cliff-tablib: https://github.com/dreamhost/cliff-tablib diff --git a/doc/source/show_commands.rst b/doc/source/show_commands.rst index 157b1bf5..87512855 100644 --- a/doc/source/show_commands.rst +++ b/doc/source/show_commands.rst @@ -100,11 +100,28 @@ the field name is the key. GID: 1000 Modified Time: 1393531476.9587486 +json +---- + +The ``json`` formatter produces a JSON object where the field name +is the key. + +:: + + (.venv)$ cliffdemo file -f json setup.py + { + "Modified Time": 1438726433.8055942, + "GID": 1000, + "UID": 1000, + "Name": "setup.py", + "Size": 1028 + } + Other Formatters ---------------- -Formatters using tablib_ to produce JSON and HTML are available -as part of `cliff-tablib`_. +A formatter using tablib_ to produce HTML is available as part of +`cliff-tablib`_. .. _cliff-tablib: https://github.com/dreamhost/cliff-tablib diff --git a/setup.cfg b/setup.cfg index 648c6e3f..e3c901ad 100644 --- a/setup.cfg +++ b/setup.cfg @@ -31,12 +31,14 @@ cliff.formatter.list = csv = cliff.formatters.commaseparated:CSVLister value = cliff.formatters.value:ValueFormatter yaml = cliff.formatters.yaml_format:YAMLFormatter + json = cliff.formatters.json_format:JSONFormatter cliff.formatter.show = table = cliff.formatters.table:TableFormatter shell = cliff.formatters.shell:ShellFormatter value = cliff.formatters.value:ValueFormatter yaml = cliff.formatters.yaml_format:YAMLFormatter + json = cliff.formatters.json_format:JSONFormatter cliff.formatter.completion = bash = cliff.complete:CompleteBash