Output formatting (table/csv/json) #6

Open
opened 2026-05-16 10:02:14 +02:00 by heiko · 1 comment
Owner

Plan 9: Output formatting

Goal

Parse the Columns: and Separator: headers already present in BasicResult
and offer structured output modes: raw (current default), table, CSV, JSON.

Where the data is

BasicResult already has:

Columns  string
Separator string
Body     io.ReadCloser

Separator defaults to space per the spec; \t is the tab variant.

Design

New flag

Add --format to main.go:

--format raw|table|csv|json   (default: raw)

New function in cmd/joker/

func writeOutput(w io.Writer, result dmapi.Result, format string) error

Reads result.Status() for the Columns/Separator fields, reads the body,
and renders accordingly.

  • raw: current io.Copy behavior — zero change
  • table: text/tabwriter with column headers from Columns
  • csv: encoding/csv, columns from Columns
  • json: one JSON object per line, keys from Columns

What "Columns" looks like

The Columns header is a comma-separated list of column names, e.g.:

Columns: domain,status,expiry-date,autorenew

Rows in the body are space- or tab-separated (per Separator).

Caveats

  • Not all endpoints return columnar data (e.g. query-profile, query-whois
    return key:value lines). For those, Columns is empty; fall back to raw.
  • dns-zone-get returns raw zone file text. Always raw.
  • The result.(*BasicResult) type assertion is needed to access Columns;
    the Result interface only exposes io.Reader. Cast defensively.

Implementation order

  1. Add --format flag (no-op initially, always raw)
  2. Implement table (most useful)
  3. Implement csv
  4. Implement json
# Plan 9: Output formatting ## Goal Parse the `Columns:` and `Separator:` headers already present in `BasicResult` and offer structured output modes: raw (current default), table, CSV, JSON. ## Where the data is `BasicResult` already has: ```go Columns string Separator string Body io.ReadCloser ``` `Separator` defaults to space per the spec; `\t` is the tab variant. ## Design ### New flag Add `--format` to `main.go`: ``` --format raw|table|csv|json (default: raw) ``` ### New function in `cmd/joker/` ```go func writeOutput(w io.Writer, result dmapi.Result, format string) error ``` Reads `result.Status()` for the `Columns`/`Separator` fields, reads the body, and renders accordingly. - `raw`: current `io.Copy` behavior — zero change - `table`: `text/tabwriter` with column headers from `Columns` - `csv`: `encoding/csv`, columns from `Columns` - `json`: one JSON object per line, keys from `Columns` ### What "Columns" looks like The `Columns` header is a comma-separated list of column names, e.g.: ``` Columns: domain,status,expiry-date,autorenew ``` Rows in the body are space- or tab-separated (per `Separator`). ### Caveats - Not all endpoints return columnar data (e.g. `query-profile`, `query-whois` return key:value lines). For those, `Columns` is empty; fall back to `raw`. - `dns-zone-get` returns raw zone file text. Always `raw`. - The `result.(*BasicResult)` type assertion is needed to access `Columns`; the `Result` interface only exposes `io.Reader`. Cast defensively. ## Implementation order 1. Add `--format` flag (no-op initially, always raw) 2. Implement `table` (most useful) 3. Implement `csv` 4. Implement `json`
Author
Owner

AI attribution comment added per repository instruction for this open issue.\n\n(co)authored by ai:gpt-5-codex

AI attribution comment added per repository instruction for this open issue.\n\n(co)authored by ai:gpt-5-codex
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
IUS/joker-dmapi-client#6
No description provided.