A simple cli tool to print JSON data as a table in the terminal.
Project description
jtbl
A simple cli tool to print JSON data as a table in the terminal.
jtbl
accepts piped JSON data from stdin
and outputs a text table representation to stdout
. e.g:
$ cat cities.json | jtbl
LatD LatM LatS NS LonD LonM LonS EW City State
------ ------ ------ ---- ------ ------ ------ ---- ----------------- -------
41 5 59 N 80 39 0 W Youngstown OH
42 52 48 N 97 23 23 W Yankton SD
46 35 59 N 120 30 36 W Yakima WA
42 16 12 N 71 48 0 W Worcester MA
43 37 48 N 89 46 11 W Wisconsin Dells WI
36 5 59 N 80 15 0 W Winston-Salem NC
49 52 48 N 97 9 0 W Winnipeg MB
jtbl
expects a JSON array of JSON objects or JSON Lines.
It can be useful to JSONify command line output with jc
, filter through jq
, and present in jtbl
:
$ jc ifconfig | jq -c '.[] | {name, type, ipv4_addr, ipv4_mask}'| jtbl
name type ipv4_addr ipv4_mask
------- -------------- -------------- -------------
docker0 Ethernet 172.17.0.1 255.255.0.0
ens33 Ethernet 192.168.71.146 255.255.255.0
lo Local Loopback 127.0.0.1 255.0.0.0
Notice the
-c
flag used injq
to produce valid JSON Lines output forjtbl
consumption.
Installation
pip3 install --upgrade jtbl
Usage
Just pipe JSON data to jtbl
. (e.g. cat
a JSON file, jc
, jq
, aws
cli, kubectl
, etc.)
$ <JSON Source> | jtbl
Compatible JSON Formats
jtbl
works best with a shallow array of JSON objects. Each object should have a few elements that will be turned into table columns. Fortunately, this is how many APIs present their data.
JSON Array Example
[
{
"unit": "proc-sys-fs-binfmt_misc.automount",
"load": "loaded",
"active": "active",
"sub": "waiting",
"description": "Arbitrary Executable File Formats File System Automount Point"
},
{
"unit": "sys-devices-pci0000:00-0000:00:07.1-ata2-host2-target2:0:0-2:0:0:0-block-sr0.device",
"load": "loaded",
"active": "active",
"sub": "plugged",
"description": "VMware_Virtual_IDE_CDROM_Drive"
},
...
]
jtbl
can also work with JSON Lines format with similar features.
JSON Lines Example
{"name": "docker0", type": "Ethernet", "ipv4_addr": "172.17.0.1", "ipv4_mask": "255.255.0.0"}
{"name": "ens33", "type": "Ethernet", "ipv4_addr": "192.168.71.146", "ipv4_mask": "255.255.255.0"}
{"name": "lo", "type": "Local Loopback", "ipv4_addr": "127.0.0.1", "ipv4_mask": "255.0.0.0"}
Filtering the JSON Input
If there are too many elements, or the data in the elements are too large, the table may not fit in the terminal screen. In this case you can use a JSON filter like jq
to send jtbl
only the elements you are interested in:
The following example uses jq
to filter and then again to 'slurp' the filtered elements into a proper JSON array.
jq
Slurp Method
$ cat /etc/passwd | jc --passwd | jq '.[] | {username, shell}' | jq -s
[
{
"username": "root",
"shell": "/bin/bash"
},
{
"username": "bin",
"shell": "/sbin/nologin"
},
{
"username": "daemon",
"shell": "/sbin/nologin"
},
...
]
Or you can use the -c
option in jq
to send the data compact, which will effectively be JSON Lines format, which jtbl
can understand:
jq
JSON Lines Method
$ cat /etc/passwd | jc --passwd | jq -c '.[] | {username, shell}'
{"username":"root","shell":"/bin/bash"}
{"username":"bin","shell":"/sbin/nologin"}
{"username":"daemon","shell":"/sbin/nologin"}
...
When piping either of these to jtbl
you get the following result:
username shell
--------------- --------------
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
...
Working with Deeper JSON Structures
jtbl
will happily dump deeply nested JSON structures into a table, but usually this is not what you are looking for.
$ jc dig www.cnn.com | jtbl
id opcode status flags query_num answer_num authority_num additional_num question answer query_time server when rcvd
----- -------- -------- ----------------- ----------- ------------ --------------- ---------------- ----------------- ----------------- ------------ -------- ----------------- ------
25618 QUERY NOERROR ['qr', 'rd', 'ra' 1 5 0 1 {'name': 'www.cnn [{'name': 'www.cn 34 2600 Fri Mar 06 07:25: 143
] .com.', 'class': n.com.', 'class': 23 PST 2020
'IN', 'type': 'A' 'IN', 'type': 'C
} NAME', 'ttl': 264
, 'data': 'turner
-tls.map.fastly.n
et.'}, {'name': '
turner-tls.map.fa
stly.net.', 'clas
s': 'IN', 'type':
...
To get to the data you are interested in you can use a JSON filter like jq
do dive deeper.
Diving Deeper into the JSON with jq
$ jc dig www.cnn.com | jq '.[].answer'
[
{
"name": "www.cnn.com.",
"class": "IN",
"type": "CNAME",
"ttl": 90,
"data": "turner-tls.map.fastly.net."
},
{
"name": "turner-tls.map.fastly.net.",
"class": "IN",
"type": "A",
"ttl": 20,
"data": "151.101.1.67"
}
...
]
This will produce the following table in jtbl
name class type ttl data
----------------- ------- ------ ----- -----------------
www.cnn.com. IN CNAME 72 turner-tls.map.fa
stly.net.
turner-tls.map.fa IN A 17 151.101.1.67
stly.net.
turner-tls.map.fa IN A 17 151.101.193.67
stly.net.
turner-tls.map.fa IN A 17 151.101.65.67
stly.net.
turner-tls.map.fa IN A 17 151.101.129.67
stly.net.
Column Width
jtbl
will attempt to shrink columns to a sane size if it detects the output is wider than the terminal width. It's not perfect and will be improved.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.