Initial CLI implementation

This commit is contained in:
Kashav Madan 2017-05-13 16:33:44 -04:00
parent 0623bd8fbd
commit 043e06f18f
2 changed files with 159 additions and 1 deletions

View File

@ -23,7 +23,7 @@ To start using GJSON, install Go and run `go get`:
$ go get -u github.com/tidwall/gjson
```
This will retrieve the library.
This will retrieve the library. [You can also use GJSON as a CLI.](#use-as-cli)
## Get a value
Get searches json for the specified path. A path is in dot syntax, such as "name.last" or "age". This function expects that the json is well-formed. Bad json will not panic, but it may return back unexpected results. When the value is found it's returned immediately.
@ -409,6 +409,66 @@ widget.text.size
*These benchmarks were run on a MacBook Pro 15" 2.8 GHz Intel Core i7 using Go 1.8.*
## Use as CLI
### Installation
```sh
$ go get -u github.com/tidwall/gjson/...
$ which gjson
$GOPATH/bin/gjson
```
### Usage
View the help dialogue with the `-help` flag.
```sh
$ gjson -help
usage: gjson [options] [path ...]
-in string
read JSON data from this file instead of stdin
-incl-path
include paths in output
-out string
write result to this file instead of stdout
-version
print version and exit
```
By default, GJSON reads from stdin and writes to stdout. Use the `-in` / `-out` flags to specify files to read to / write from. Note that GJSON **overwrites** the contents of `-out` (and creates the file if it doesn't exist yet).
GJSON expects one or more paths as command line arguments. A path with escaped characters should be wrapped in quotes.
### Examples
```sh
$ echo '{"name":{"first":"Janet","last":"Prichard"},"age":47}' | gjson name.last
Prichard
```
The following examples use the JSON data from [this section](#path-syntax).
```sh
$ gjson name.last < data.json
Anderson
```
```sh
$ gjson name.last age "fav\.movie" < data.json > out
$ cat out
Anderson
37
Deer Hunter
```
```sh
$ gjson -in data.json -out out -include-path children children.#
$ cat out
"children" : ["Sara","Alex","Jack"]
"children.#" : 3
```
## Contact
Josh Baker [@tidwall](http://twitter.com/tidwall)

98
cmd/gjson/gjson.go Normal file
View File

@ -0,0 +1,98 @@
package main
import (
"errors"
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"github.com/tidwall/gjson"
)
const version = "0.0.1"
var options struct {
in string
out string
includePath bool
version bool
}
func readInput() ([]byte, error) {
if len(options.in) > 0 {
return ioutil.ReadFile(options.in)
}
// Check that stdin is not empty.
stat, err := os.Stdin.Stat()
if err != nil {
return []byte{}, err
}
if (stat.Mode() & os.ModeCharDevice) != 0 {
return []byte{}, errors.New("expected JSON data from stdin (run gjson -help)")
}
return ioutil.ReadAll(os.Stdin)
}
func printOutput(results []gjson.Result) error {
var (
out *os.File
err error
)
if len(options.out) > 0 {
out, err = os.Create(options.out)
if err != nil {
return err
}
defer out.Close()
} else {
out = os.Stdout
}
for i, result := range results {
if options.includePath {
fmt.Fprintf(out, "\"%s\" : ", flag.Args()[i])
}
fmt.Fprintln(out, result)
}
return nil
}
func main() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "usage: %s [options] [path ...]\n", os.Args[0])
flag.PrintDefaults()
}
flag.StringVar(&options.in, "in", "", "read JSON data from this file instead of stdin")
flag.StringVar(&options.out, "out", "", "write result to this file instead of stdout")
flag.BoolVar(&options.includePath, "include-path", false, "include paths in output")
flag.BoolVar(&options.version, "version", false, "print version and exit")
flag.Parse()
if options.version {
fmt.Printf("gjson v%v\n", version)
os.Exit(0)
}
if len(flag.Args()) == 0 {
flag.Usage()
os.Exit(1)
}
bytes, err := readInput()
if err != nil {
log.Fatal(err.Error())
}
results := gjson.GetMany(string(bytes), flag.Args()...)
err = printOutput(results)
if err != nil {
log.Fatal(err.Error())
}
}