Skip to content

Commit

Permalink
feat: add --output=jsonpointer (#644)
Browse files Browse the repository at this point in the history
  • Loading branch information
hperl committed Dec 5, 2022
1 parent d608f03 commit e8188f8
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
52 changes: 43 additions & 9 deletions cmdx/printing.go
Expand Up @@ -12,6 +12,7 @@ import (
"strings"
"text/tabwriter"

"github.com/go-openapi/jsonpointer"
"github.com/goccy/go-yaml"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -39,13 +40,14 @@ type (
)

const (
FormatQuiet format = "quiet"
FormatTable format = "table"
FormatJSON format = "json"
FormatJSONPath format = "jsonpath"
FormatJSONPretty format = "json-pretty"
FormatYAML format = "yaml"
FormatDefault format = "default"
FormatQuiet format = "quiet"
FormatTable format = "table"
FormatJSON format = "json"
FormatJSONPath format = "jsonpath"
FormatJSONPointer format = "jsonpointer"
FormatJSONPretty format = "json-pretty"
FormatYAML format = "yaml"
FormatDefault format = "default"

FlagFormat = "format"

Expand Down Expand Up @@ -84,6 +86,8 @@ func PrintRow(cmd *cobra.Command, row TableRow) {
printJSON(cmd.OutOrStdout(), row.Interface(), true, "")
case FormatJSONPath:
printJSON(cmd.OutOrStdout(), row.Interface(), true, getPath(cmd))
case FormatJSONPointer:
printJSON(cmd.OutOrStdout(), filterJSONPointer(cmd, row.Interface()), true, "")
case FormatTable, FormatDefault:
w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 8, 1, '\t', 0)

Expand All @@ -96,6 +100,26 @@ func PrintRow(cmd *cobra.Command, row TableRow) {
}
}

func filterJSONPointer(cmd *cobra.Command, data any) any {
f, err := cmd.Flags().GetString(FlagFormat)
// unexpected error
Must(err, "flag access error: %s", err)
_, jsonptr, found := strings.Cut(f, "=")
if !found {
_, _ = fmt.Fprintf(os.Stderr,
"Format %s is missing a JSON pointer, e.g., --%s=%s=<jsonpointer>. The path syntax is described at https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-pointer-07.",
f, FlagFormat, f)
os.Exit(1)
}
ptr, err := jsonpointer.New(jsonptr)
Must(err, "invalid JSON pointer: %s", err)

result, _, err := ptr.Get(data)
Must(err, "failed to apply JSON pointer: %s", err)

return result
}

func PrintTable(cmd *cobra.Command, table Table) {
f := getFormat(cmd)

Expand All @@ -121,6 +145,8 @@ func PrintTable(cmd *cobra.Command, table Table) {
printJSON(cmd.OutOrStdout(), table.Interface(), true, "")
case FormatJSONPath:
printJSON(cmd.OutOrStdout(), table.Interface(), true, getPath(cmd))
case FormatJSONPointer:
printJSON(cmd.OutOrStdout(), filterJSONPointer(cmd, table.Interface()), true, "")
case FormatYAML:
printYAML(cmd.OutOrStdout(), table.Interface())
default:
Expand Down Expand Up @@ -164,6 +190,12 @@ func PrintJSONAble(cmd *cobra.Command, d interface{ String() string }) {
v = i
}
printJSON(cmd.OutOrStdout(), v, true, path)
case FormatJSONPointer:
var v interface{} = d
if i, ok := d.(interfacer); ok {
v = i
}
printJSON(cmd.OutOrStdout(), filterJSONPointer(cmd, v), true, "")
case FormatYAML:
var v interface{} = d
if i, ok := d.(interfacer); ok {
Expand Down Expand Up @@ -200,6 +232,8 @@ func getFormat(cmd *cobra.Command) format {
return FormatJSON
case strings.HasPrefix(f, string(FormatJSONPath)):
return FormatJSONPath
case strings.HasPrefix(f, string(FormatJSONPointer)):
return FormatJSONPointer
case f == string(FormatJSONPretty):
return FormatJSONPretty
case f == string(FormatYAML):
Expand Down Expand Up @@ -249,12 +283,12 @@ func printYAML(w io.Writer, v interface{}) {
}

func RegisterJSONFormatFlags(flags *pflag.FlagSet) {
flags.String(FlagFormat, string(FormatDefault), fmt.Sprintf("Set the output format. One of %s, %s, %s, %s and %s.", FormatDefault, FormatJSON, FormatYAML, FormatJSONPretty, FormatJSONPath))
flags.String(FlagFormat, string(FormatDefault), fmt.Sprintf("Set the output format. One of %s, %s, %s, %s, %s and %s.", FormatDefault, FormatJSON, FormatYAML, FormatJSONPretty, FormatJSONPath, FormatJSONPointer))
}

func RegisterFormatFlags(flags *pflag.FlagSet) {
RegisterNoiseFlags(flags)
flags.String(FlagFormat, string(FormatDefault), fmt.Sprintf("Set the output format. One of %s, %s, %s, %s, and %s.", FormatTable, FormatJSON, FormatYAML, FormatJSONPretty, FormatJSONPath))
flags.String(FlagFormat, string(FormatDefault), fmt.Sprintf("Set the output format. One of %s, %s, %s, %s, %s and %s.", FormatTable, FormatJSON, FormatYAML, FormatJSONPretty, FormatJSONPath, FormatJSONPointer))
}

type bodyer interface {
Expand Down
18 changes: 17 additions & 1 deletion cmdx/printing_test.go
Expand Up @@ -128,6 +128,18 @@ func TestPrinting(t *testing.T) {
fArgs: []string{"--" + FlagFormat, string(FormatJSONPretty)},
contained: tr,
},
{
fArgs: []string{"--" + FlagFormat, string(FormatJSONPointer) + "=/0"},
contained: []string{"AAA"},
},
{
fArgs: []string{"--" + FlagFormat, string(FormatJSONPointer) + "=/2"},
contained: []string{"CCC"},
},
{
fArgs: []string{"--" + FlagFormat, string(FormatJSONPointer) + "=/1"},
contained: []string{"BBB"},
},
{
fArgs: []string{"--" + FlagFormat, string(FormatJSONPath) + "=0"},
contained: []string{"AAA"},
Expand Down Expand Up @@ -224,6 +236,10 @@ func TestPrinting(t *testing.T) {
fArgs: []string{"--" + FlagFormat, string(FormatJSONPath) + "=1.1"},
contained: []string{tb.t[1][1]},
},
{
fArgs: []string{"--" + FlagFormat, string(FormatJSONPointer) + "=/1/1"},
contained: []string{tb.t[1][1]},
},
{
fArgs: []string{"--" + FlagFormat, string(FormatYAML)},
contained: append(tb.t[0], tb.t[1]...),
Expand Down Expand Up @@ -330,7 +346,7 @@ func TestPrinting(t *testing.T) {

t.Run("method=jsonable", func(t *testing.T) {
t.Run("case=nil", func(t *testing.T) {
for _, f := range []format{FormatDefault, FormatJSON, FormatJSONPretty, FormatJSONPath, FormatYAML} {
for _, f := range []format{FormatDefault, FormatJSON, FormatJSONPretty, FormatJSONPath, FormatJSONPointer, FormatYAML} {
t.Run("format="+string(f), func(t *testing.T) {
out := &bytes.Buffer{}
cmd := &cobra.Command{}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Expand Up @@ -133,6 +133,7 @@ require (
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/errors v0.20.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/strfmt v0.21.3 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-pdf/fpdf v0.6.0 // indirect
Expand Down

0 comments on commit e8188f8

Please sign in to comment.