Files
kopia/cli/json_output.go
Jarek Kowalski 74833cefcb cli: added standard --json flags to several commands (#910)
* cli: added standard --json flags to several commands

Fixes #272

* Update flag description

Co-authored-by: Julio López <julio+gh@kasten.io>
2021-03-25 17:55:18 -07:00

118 lines
2.1 KiB
Go

package cli
import (
"encoding/json"
"github.com/alecthomas/kingpin"
"github.com/kopia/kopia/snapshot"
)
var (
jsonOutput = false
jsonIndent = false
jsonVerbose = false // output addnon-essential stats as part of JSON
)
func registerJSONOutputFlags(cmd *kingpin.CmdClause) {
cmd.Flag("json", "Output result in JSON format to stdout").BoolVar(&jsonOutput)
cmd.Flag("json-indent", "Output result in indented JSON format to stdout").Hidden().BoolVar(&jsonIndent)
cmd.Flag("json-verbose", "Output non-essential data (e.g. statistics) in JSON format").Hidden().BoolVar(&jsonVerbose)
}
func cleanupSnapshotManifestForJSON(v *snapshot.Manifest) interface{} {
m := *v
if !jsonVerbose {
return struct {
*snapshot.Manifest
// trick to remove 'stats' completely.
Stats string `json:"stats,omitempty"`
}{Manifest: v}
}
return &m
}
func cleanupSnapshotManifestListForJSON(manifests []*snapshot.Manifest) interface{} {
var res []interface{}
for _, m := range manifests {
res = append(res, cleanupSnapshotManifestForJSON(m))
}
return res
}
func cleanupForJSON(v interface{}) interface{} {
switch v := v.(type) {
case *snapshot.Manifest:
return cleanupSnapshotManifestForJSON(v)
case []*snapshot.Manifest:
return cleanupSnapshotManifestListForJSON(v)
default:
return v
}
}
func jsonBytes(v interface{}) []byte {
return jsonIndentedBytes(v, "")
}
func jsonIndentedBytes(v interface{}, indent string) []byte {
v = cleanupForJSON(v)
var (
b []byte
err error
)
if jsonIndent {
b, err = json.MarshalIndent(v, indent+"", indent+" ")
} else {
b, err = json.Marshal(v)
}
if err != nil {
panic("error serializing JSON, that should not happen: " + err.Error())
}
return b
}
type jsonList struct {
separator string
}
func (l *jsonList) begin() {
if jsonOutput {
printStdout("[")
if !jsonIndent {
l.separator = "\n "
}
}
}
func (l *jsonList) end() {
if jsonOutput {
if !jsonIndent {
printStdout("\n")
}
printStdout("]")
}
}
func (l *jsonList) emit(v interface{}) {
printStdout(l.separator)
printStdout("%s", jsonBytes(v))
if jsonIndent {
l.separator = ","
} else {
l.separator = ",\n "
}
}