diff --git a/README.md b/README.md index 528cbd3..2031ea4 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ and more, written in pure Go, and inspired by [skate](https://github.com/charmbr

-`pda!` stores key-value pairs natively as [newline-delimited JSON](https://en.wikipedia.org/wiki/JSON_streaming#Newline-delimited_JSON) files. The `list` command outputs tabular data by default, but also supports [CSV](https://en.wikipedia.org/wiki/Comma-separated_values), [TSV](https://en.wikipedia.org/wiki/Tab-separated_values), [Markdown](https://en.wikipedia.org/wiki/Markdown) and [HTML](https://en.wikipedia.org/wiki/HTML_element#Tables) tables, and raw NDJSON. Because every store is in plaintext, Git versioning is pretty easy: auto-committing, pushing, and fetching can be enabled in the config to automatically version changes, or just `pda sync` regularly. +`pda!` stores key-value pairs natively as [newline-delimited JSON](https://en.wikipedia.org/wiki/JSON_streaming#Newline-delimited_JSON) files. The `list` command outputs tabular data by default, but also supports [CSV](https://en.wikipedia.org/wiki/Comma-separated_values), [TSV](https://en.wikipedia.org/wiki/Tab-separated_values), [Markdown](https://en.wikipedia.org/wiki/Markdown) and [HTML](https://en.wikipedia.org/wiki/HTML_element#Tables) tables, JSON, and raw NDJSON. Because every store is in plaintext, Git versioning is pretty easy: auto-committing, pushing, and fetching can be enabled in the config to automatically version changes, or just `pda sync` regularly.

@@ -229,7 +229,11 @@ pda ls --format csv # name,Alice,no expiry # dogs,four legged mammals,no expiry -# Or TSV, or Markdown, or HTML. +# Or as a JSON array. +pda ls --format json +# [{"key":"name","value":"Alice","encoding":"text"},{"key":"dogs","value":"four legged mammals","encoding":"text"}] + +# Or TSV, Markdown, HTML, NDJSON. # Just the count of entries. pda ls --count diff --git a/cmd/list.go b/cmd/list.go index 8c4539d..b8c0a98 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -46,11 +46,11 @@ func (e *formatEnum) String() string { return string(*e) } func (e *formatEnum) Set(v string) error { switch v { - case "table", "tsv", "csv", "html", "markdown", "ndjson": + case "table", "tsv", "csv", "html", "markdown", "ndjson", "json": *e = formatEnum(v) return nil default: - return fmt.Errorf("must be one of 'table', 'tsv', 'csv', 'html', 'markdown', or 'ndjson'") + return fmt.Errorf("must be one of 'table', 'tsv', 'csv', 'html', 'markdown', 'ndjson', or 'json'") } } @@ -196,6 +196,24 @@ func list(cmd *cobra.Command, args []string) error { return nil } + // JSON format: emit a single JSON array + if listFormat.String() == "json" { + var entries []jsonEntry + for _, e := range filtered { + je, err := encodeJsonEntry(e, recipient) + if err != nil { + return fmt.Errorf("cannot ls '%s': %v", targetDB, err) + } + entries = append(entries, je) + } + data, err := json.Marshal(entries) + if err != nil { + return fmt.Errorf("cannot ls '%s': %v", targetDB, err) + } + fmt.Fprintln(output, string(data)) + return nil + } + // Table-based formats showValues := !listNoValues tw := table.NewWriter() @@ -485,7 +503,7 @@ func init() { listCmd.Flags().BoolVar(&listNoTTL, "no-ttl", false, "suppress the TTL column") listCmd.Flags().BoolVarP(&listFull, "full", "f", false, "show full values without truncation") listCmd.Flags().BoolVar(&listNoHeader, "no-header", false, "suppress the header row") - listCmd.Flags().VarP(&listFormat, "format", "o", "output format (table|tsv|csv|markdown|html|ndjson)") + listCmd.Flags().VarP(&listFormat, "format", "o", "output format (table|tsv|csv|markdown|html|ndjson|json)") listCmd.Flags().StringSliceP("key", "k", nil, "filter keys with glob pattern (repeatable)") listCmd.Flags().StringSliceP("value", "v", nil, "filter values with glob pattern (repeatable)") rootCmd.AddCommand(listCmd) diff --git a/testdata/help-list.ct b/testdata/help-list.ct index 80e64f5..f513a64 100644 --- a/testdata/help-list.ct +++ b/testdata/help-list.ct @@ -11,7 +11,7 @@ Aliases: Flags: -b, --base64 view binary data as base64 -c, --count print only the count of matching entries - -o, --format format output format (table|tsv|csv|markdown|html|ndjson) (default table) + -o, --format format output format (table|tsv|csv|markdown|html|ndjson|json) (default table) -f, --full show full values without truncation -h, --help help for list -k, --key strings filter keys with glob pattern (repeatable) @@ -31,7 +31,7 @@ Aliases: Flags: -b, --base64 view binary data as base64 -c, --count print only the count of matching entries - -o, --format format output format (table|tsv|csv|markdown|html|ndjson) (default table) + -o, --format format output format (table|tsv|csv|markdown|html|ndjson|json) (default table) -f, --full show full values without truncation -h, --help help for list -k, --key strings filter keys with glob pattern (repeatable) diff --git a/testdata/list-format-json.ct b/testdata/list-format-json.ct new file mode 100644 index 0000000..6c2cd85 --- /dev/null +++ b/testdata/list-format-json.ct @@ -0,0 +1,5 @@ +# JSON array format output via list +$ pda set a@jf 1 +$ pda set b@jf 2 +$ pda ls jf --format json +[{"key":"a","value":"1","encoding":"text"},{"key":"b","value":"2","encoding":"text"}]