diff --git a/cmd/jf/main.go b/cmd/jf/main.go index 461c946..7317691 100644 --- a/cmd/jf/main.go +++ b/cmd/jf/main.go @@ -5,21 +5,30 @@ import ( "fmt" "io/ioutil" "os" + "strings" "jsonfind/pkg/scout" "github.com/urfave/cli/v2" ) -func main() { +const flagParentPaths = "parent-paths" +func main() { app := &cli.App{ Name: "jf", Usage: "JSONFind", UsageText: "jf ", - Version: "1.0.2", + Version: "1.0.3", Description: "Search a JSON file for a specified value and output full paths of each occurrence found", Action: doSearch, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: flagParentPaths, + Usage: "Renders the parent paths only", + Aliases: []string{"p"}, + }, + }, } if err := app.Run(os.Args); err != nil { @@ -52,14 +61,37 @@ func doSearch(c *cli.Context) error { } for _, occurrence := range found { - fmt.Println(occurrence) + if c.Bool(flagParentPaths) { + fmt.Println(splitToParentPath(occurrence)) + } else { + fmt.Println(occurrence) + } } return nil } +func splitToParentPath(path string) string { + pathElements := strings.Split(path, ".") + if len(pathElements) > 0 && len(pathElements) < 3 { + return "." + } + + lastElement := pathElements[len(pathElements)-1] + if len(lastElement) > 0 && lastElement[len(lastElement)-1] == ']' { + lastElement = strings.Split(lastElement, "[")[0] + pathElements = append(pathElements[:len(pathElements)-1], lastElement) + return strings.Join(pathElements, ".") + } + + return strings.Join(pathElements[:len(pathElements)-1], ".") +} + func readFile(filepath string) ([]byte, error) { jsonFile, err := os.Open(filepath) + if err != nil { + return nil, err + } defer jsonFile.Close() if err != nil { return []byte{}, err diff --git a/cmd/jf/main_test.go b/cmd/jf/main_test.go new file mode 100644 index 0000000..1fb2482 --- /dev/null +++ b/cmd/jf/main_test.go @@ -0,0 +1,28 @@ +package main + +import ( + "testing" + + "github.com/matryer/is" +) + +func Test_splitToParentPath(t *testing.T) { + is := is.New(t) + + testData := []struct { + value, + expected string + }{ + {".[2]", "."}, + {".[2].eyeColor", ".[2]"}, + {".[2].eyeColor.foobar", ".[2].eyeColor"}, + {".[2].eyeColors[2].foobar", ".[2].eyeColors[2]"}, + {".[2].eyeColors[2].foobar[3]", ".[2].eyeColors[2].foobar"}, + } + + t.Run("splitToParentPath", func(t *testing.T) { + for _, td := range testData { + is.Equal(splitToParentPath(td.value), td.expected) + } + }) +}