Skip to content

fix(cli): show nested fields in single-object table output - #193

Merged
ysyneu merged 3 commits into
mainfrom
bugfix/table-output-nested-fields
Oct 6, 2026
Merged

ysyneu merged 3 commits into
mainfrom
bugfix/table-output-nested-fields

Conversation

@ysyneu

@ysyneu ysyneu commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Problem

When a command returns a single object, the default table output listed only the object's top-level scalar fields. Arrays, nested objects and maps were skipped with no sign that anything was missing. --json and --output-format toon were not affected.

For example, a detail response like {html, recipients: [...]} printed only HTML, and a multi-line value spilled onto lines that looked like extra rows:

FIELD  VALUE
HTML   <html>
  <body style="font-family: Georgia">
    <h1>Daily report</h1>
    <p>Al...

Every command that renders through the shared generic renderer (renderGenericTable) had the same gap. That covers all generated commands plus the curated automation, monit query and Prometheus label-values commands. Any detail response whose content is nested lost that content in the table, such as PrometheusLabelValuesResponse.data or KnowledgeGetResponse.files.

Change

  • Single-object tables list every non-empty value. The FIELD/VALUE table walks the whole object. Each nested value is named by its path: struct fields use the existing upper-cased names, map entries use their key (sorted), and array elements use their index. List pages keep their column tables.
  • Table cells stay on one line. TablePrinter collapses line breaks and indentation inside a value to single spaces, so a multi-line value stays on its own row. Long values are still cut at the column width with ... unless --no-trunc is set. For a large html body the default view shows a readable one-line preview, and --no-trunc or --json returns the whole body.
  • A bare array of scalars no longer panics in table mode. Before this change, monit datasource-sls-logstores crashed with reflect: NumField of non-struct type string. It now prints JSON, like other shapes a table cannot model.

After:

FIELD                    VALUE
HTML                     <html> <body style="font-family: Georgia"> <h1>Daily report</h1> <p>All servi...
RECIPIENTS[0].PERSON_ID  1001
RECIPIENTS[0].STATUS     accepted
RECIPIENTS[1].PERSON_ID  1002
RECIPIENTS[1].REASON     no_email
RECIPIENTS[1].STATUS     skipped

Alternatives considered

  • Render arrays of objects as labeled sub-tables using the list-table columns. Rejected. Those columns are a projection: curated columns, an 8-column heuristic, and nested fields skipped. Fields nested inside array rows would still vanish without notice, for example route cases or escalation layers. Arrays of maps or of arrays cannot be laid out as columns at all.
  • Put nested values in a cell as compact JSON. Rejected. At the default cell width almost all of the content would be cut off, and timestamps would print as raw integers.
  • Print long strings as separate blocks after the table. Rejected. A 60 KB body would flood the terminal in the default view.

Tests

  • TestRenderGenericTable_DetailShowsNestedFields checks the exact output for a nested object, an array of objects, an array of scalars, a map, an any value and a nil pointer.
  • TestPrintGenericResultNestedDetailNotReduced pins that a single-object detail carrying nested fields and an oversized long field passes through printGenericResult unbounded in --json and toon modes.
  • TestRenderGenericTable_TopLevelScalarArray checks that a bare scalar array prints without a panic.

The default table output of a single-object response listed only its
top-level scalar fields. Arrays, nested objects and maps were skipped
without any sign, so `member notify --dry-run` printed the email html but
none of the per-recipient outcomes, and a detail response whose useful
content is nested looked nearly empty.

The key/value table now lists every non-empty scalar value reachable from
the object, naming nested ones by their path (OWNER.EMAIL, LABELS.env,
RECIPIENTS[0].STATUS). List pages keep their column tables.

Table cells are also folded to one line. A multi-line value such as an
email body used to spill onto following lines that read as extra rows;
line breaks and indentation now collapse to single spaces, and long values
are still truncated unless --no-trunc is set.

A bare array of scalars (monit datasource-sls-logstores) no longer panics
in table mode; it prints as JSON like other shapes a table cannot model.
A []byte or json.RawMessage field reached the key/value walk as a slice
of uint8, so it would print one row per byte instead of its value.

Byte slices are now single table cells, shown the way --json encodes
them: a json.RawMessage as its compact JSON text, any other []byte as
base64.
Nested objects, arrays, and maps in a single-object response render as
FIELD[KEY] rows in the vertical table instead of being flattened away, and
scalar top-level values no longer fall through to the JSON fallback.
@ysyneu
ysyneu merged commit 5195827 into main Oct 6, 2026
12 checks passed
@ysyneu
ysyneu deleted the bugfix/table-output-nested-fields branch October 6, 2026 08:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant