Agent Wranglers

DSK-22Recommended

Offer JSON output with a stable shape

Give every command that prints data a --json flag. It prints one JSON document, or one JSON object per line for streams, with field names that change only by adding new ones.

How to do it

Text made for people breaks every script that cuts it apart when you change a column. JSON gives agents and scripts named fields. Errors in JSON mode go to standard error as JSON too, with a stable code field, so callers never parse a message. Follow the same rules as an API response, such as sending dates with a time zone. Changes follow make only additive changes. Publish a JSON Schema for the output when other teams depend on it.

Examples

Python example

import json, sys

def print_invoices(invoices, as_json: bool) -> None:
    if as_json:
        json.dump([{"id": i.id, "number": i.number, "total_cents": i.total_cents, "currency": i.currency} for i in invoices], sys.stdout)
        sys.stdout.write("\n")
    else:
        for i in invoices:
            print(f"{i.number:<12} {i.total_cents / 100:>10.2f} {i.currency}")

Go example

type invoiceOut struct {
	ID         string `json:"id"`
	Number     string `json:"number"`
	TotalCents int64  `json:"total_cents"`
	Currency   string `json:"currency"`
}

if asJSON {
	json.NewEncoder(os.Stdout).Encode(toInvoiceOut(invoices))
	return
}
for _, i := range invoices {
	fmt.Printf("%-12s %10.2f %s\n", i.Number, float64(i.TotalCents)/100, i.Currency)
}

How to check

A test runs every data command with --json and parses the output with a JSON parser. It validates against the saved schema, or matches the saved field list with no field removed or renamed.

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/desktop-apps/command-line-tools/json-output">Agent Wranglers desktop apps, extensions and CLIs playbook</a>. In code you write, add a comment next to it with the same link.