Skip to content
jc-rs
GitHub

Table conversion guide

Convert an ASCII table to JSON on the command line

An aligned text table often exposes enough structure to recover records: headers name the columns, while spacing or borders mark their boundaries. jc-rs handles simple fixed-width output and bordered tables whose logical rows span several lines. Arbitrary prose does not provide those guarantees.

By · Published · Input and output examples checked against both jc-rs ASCII table parsers

Inputaligned table
Parsejc-rs
ShapeJSON rows
Queryjq

Choose by row structure, not border style

jc-rs has two related parsers. Both accept ASCII or Unicode table characters and strip terminal ANSI color sequences. Choose between them based on whether one data row fits on one physical line.

One physical line per record

Simple, Markdown-like, or bordered column tables

One logical record spans lines

Pretty bordered tables with separators between rows

A reliable delimiter exists

Prefer the explicit delimiter over visual alignment

The source already offers JSON

native output

Keep the native schema; no table parser is needed

Simple table: one line becomes one object

The first non-empty row supplies the headers. Spacing in that row establishes column positions; the following rows are read against those positions.

table.txt
NAME        STATUS     PORT
api         healthy    8080
worker      draining   9090
Bash
jc-rs -p --asciitable < table.txt
JSON
[
  {
    "name": "api",
    "port": "8080",
    "status": "healthy"
  },
  {
    "name": "worker",
    "port": "9090",
    "status": "draining"
  }
]

The output is an array, so jq can filter it without returning to column offsets. This example converts the port explicitly because the table parser preserves it as text:

Filter the JSON rows
jc-rs --asciitable < table.txt |
  jq 'map(select((.port | tonumber) >= 9000))'

Multiline table: preserve wrapped cell content

In a pretty table, border rows identify where one logical record ends and the next starts. The multiline parser joins successive physical lines in the same cell with a newline.

multiline-table.txt
+----------+--------+--------------------+
| SERVICE  | OWNER  | NOTE               |
+==========+========+====================+
| api      | ops    | waiting for        |
|          |        | database migration |
+----------+--------+--------------------+
| worker   | data   | ready              |
+----------+--------+--------------------+
Bash
jc-rs -p --asciitable-m < multiline-table.txt
JSON
[
  {
    "note": "waiting for\ndatabase migration",
    "owner": "ops",
    "service": "api"
  },
  {
    "note": "ready",
    "owner": "data",
    "service": "worker"
  }
]

The multiline parser intentionally accepts “pretty” bordered tables. If it detects a simple or Markdown table, it returns an error and directs you to --asciitable; that prevents ordinary rows from being collapsed together by guesswork.

How headers become JSON keys

Headers are lowercased and normalized toward snake_case. Spaces between words become underscores, punctuation is normalized, and an empty cell becomes null. Multiline header bands are collapsed into combined names.

Service Nameservice_name
PORTport
two header bands: Disk / Useddisk_used
empty data cellnull

Do not assume a numeric-looking cell became a JSON number. Inspect the actual result and use jq's tonumber at the point where numeric semantics are required. This also makes conversion failures visible.

“Text to JSON” only works when the text has a schema

A table parser can recover explicit columns. It cannot know whether a sentence, stack trace, paragraph, or casually spaced note contains a name, timestamp, status, or message. Converting arbitrary prose would require domain rules, not a universal parser.

Good table input

A header row, repeatable column positions, and one clear record boundary.

Not enough structure

Wrapped prose, inconsistent labels, or whitespace that changes meaning from line to line.

If the source is delimited, use the CSV parser or TSV parser. If each line is genuinely key/value data, inspect the key/value parser. Pick the grammar the producer actually writes.

When columns land in the wrong field

  1. 01Capture raw output rather than copying from a rendered web page or proportional font. Character positions are part of the input.
  2. 02Make the producer use a wide, non-interactive layout when possible. Terminal-width wrapping can turn one record into several unrelated lines.
  3. 03Check the header first. A header centered differently from its data may establish the wrong boundary even when the rows look aligned to a person.
  4. 04Use --asciitable-m only when explicit border rows delimit logical records. Otherwise keep the simple parser.
  5. 05Compare several output versions. If a command changes its layout across systems, prefer that command's dedicated jc-rs parser when one exists.

Choose the most specific parser available

The parser references document each input contract. The Bash and jq guide explains how to carry the resulting rows safely into a larger script.

Install jc-rs