gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

commit 2dc87fb620b38fc93f7bff16ee47e3ec1f6321c5
parent 837a255e5a66252a880942ba5d86b9989dfa175a
Author: francoispqt <francois@parquet.ninja>
Date:   Sun, 24 Jun 2018 20:06:43 +0800

improve args parsing and add documentation

Diffstat:
Mgojay/README.md | 32++++++++++++++++++++------------
Mgojay/main.go | 93++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Dgojay/tests/json.go | 284-------------------------------------------------------------------------------
3 files changed, 69 insertions(+), 340 deletions(-)

diff --git a/gojay/README.md b/gojay/README.md @@ -10,30 +10,38 @@ go install github.com/francoispqt/gojay/gojay ## Generate code -- for specific types in a go package, to stdout: -```sh -gojay -s github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice -``` -or simply +### Basic command + +The basic command is strait forward and easy to use: ```sh -gojay github.com/francoispqt/gojay/gojay/tests A,B,StrSlice +gojay github.com/some/package TypeA,TypeB,TypeC output.go ``` +If you just want to the output to stdout, omit the third parameter. -- for specific types in a go package, write to a file: +### Using flags + +- p package to parse, relative path to $GOPATH/src +- s file/dir to path, can be a relative or absolute path +- t types to generate (comma separated) +- o output file (relative or absolute path) + +Examples: +- Specific types in a go package, to stdout: ```sh -gojay -s github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice -o output.go +gojay -p github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice ``` -- for all types annotated by a //gojay:json (don't specify any type) in a package: +- Specific types in a go package, write to a file: ```sh -gojay -s github.com/francoispqt/gojay/gojay/tests -o output.go +gojay -p github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice -o output.go ``` -- for types annotated in a specific file +- Specific types in a go file, to stdout: ```sh -gojay -s path/to/gofile.go -o output.go +gojay -s somegofile.go -t SomeType ``` + ## Gojay tags You can add tags to your structs to control: diff --git a/gojay/main.go b/gojay/main.go @@ -3,6 +3,7 @@ package main import ( + "errors" "flag" "io/ioutil" "log" @@ -12,9 +13,16 @@ import ( ) var dst = flag.String("o", "", "destination file to output generated implementations") -var src = flag.String("s", "", "source dir or file") +var src = flag.String("s", "", "source dir or file (absolute or relative path)") +var pkg = flag.String("p", "", "go package") var types = flag.String("t", "", "types to generate") +var ErrNoPathProvided = errors.New("You must provide a path or a package name") + +type stringWriter interface { + WriteString(string) (int, error) +} + func hasAnnotation(fP string) bool { b, err := ioutil.ReadFile(fP) if err != nil { @@ -24,62 +32,69 @@ func hasAnnotation(fP string) bool { } func resolvePath(p string) (string, error) { - if _, err := os.Stat(p); err != nil { - if os.IsNotExist(err) { - return filepath.Abs(os.Getenv("GOPATH") + "/src/" + *src) - } else { - return "", err - } + if fullPath, err := filepath.Abs(p); err != nil { + return "", err + } else if _, err := os.Stat(fullPath); err != nil { + return "", err + } else { + return fullPath, nil } - return p, nil } // getPath returns either the path given as argument or current working directory func getPath() (string, error) { - var err error - var p string - if *src != "" { // if src is present parse from src - p, err = filepath.Abs(*src) - if err != nil { - return "", err - } - return resolvePath(p) + // if pkg is set, resolve pkg path + if *pkg != "" { + return resolvePath(os.Getenv("GOPATH") + "/src/" + *pkg) + } else if *src != "" { // if src is present parse from src + return resolvePath(*src) } else if len(os.Args) > 1 { // else if there is a command line arg, use it as path to a package $GOPATH/src/os.Args[1] - p, err = filepath.Abs(os.Args[1]) - if err != nil { - return "", err - } - return resolvePath(p) - } else { - p, err = os.Getwd() - if err != nil { - return "", err - } + return resolvePath(os.Getenv("GOPATH") + "/src/" + os.Args[1]) } - return p, nil + return "", ErrNoPathProvided } +// getTypes returns the types to be parsed func getTypes() (t []string) { if *types != "" { // if src is present parse from src return strings.Split(*types, ",") - } else if *src == "" && *dst == "" && len(os.Args) > 2 { // else if there is a command line arg, use it as path to a package $GOPATH/src/os.Args[1] + } else if *src == "." && *dst == "" && len(os.Args) > 2 { // else if there is a command line arg, use it as path to a package $GOPATH/src/os.Args[1] return strings.Split(os.Args[2], ",") } return t } -func parseArgs() (p string, t []string, err error) { +// getOutput returns the output +func getOutput() (stringWriter, error) { + if *dst != "" { + p, err := filepath.Abs(*dst) + if err != nil { + return nil, err + } + return os.OpenFile(p, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) + } else if len(os.Args) > 3 && *src == "" && *types == "" { + p, err := filepath.Abs(os.Args[3]) + if err != nil { + return nil, err + } + return os.OpenFile(p, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) + } + return os.Stdout, nil +} + +func parseArgs() (p string, t []string, o stringWriter, err error) { flag.Parse() p, err = getPath() if err != nil { - return p, t, err + return p, t, o, err } t = getTypes() - return p, t, err + o, err = getOutput() + return p, t, o, err } func main() { - p, t, err := parseArgs() + p, t, o, err := parseArgs() if err != nil { log.Fatal(err) } @@ -96,16 +111,6 @@ func main() { log.Fatal(err) return } - // if has dst file, write to file - if *dst != "" { - f, err := os.OpenFile(*dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) - if err != nil { - log.Fatal(err) - return - } - f.WriteString(g.b.String()) - return - } - // else just print to stdout - os.Stdout.WriteString(g.b.String()) + // write content to output + o.WriteString(g.b.String()) } diff --git a/gojay/tests/json.go b/gojay/tests/json.go @@ -1,284 +0,0 @@ -// Code generated by GoJay. DO NOT EDIT. - -package tests - -import "github.com/francoispqt/gojay" - -// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray -func (v *StrSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { - var str string - if err := dec.String(&str); err != nil { - return err - } - *v = append(*v, str) - return nil -} - -// MarshalJSONArray implements gojay's MarshalerJSONArray -func (v *StrSlice) MarshalJSONArray(enc *gojay.Encoder) { - for _, s := range *v { - enc.String(s) - } -} - -// IsNil implements gojay's MarshalerJSONArray -func (v *StrSlice) IsNil() bool { - return *v == nil || len(*v) == 0 -} - -// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray -func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { - var i int - if err := dec.Int(&i); err != nil { - return err - } - *v = append(*v, i) - return nil -} - -// MarshalJSONArray implements gojay's MarshalerJSONArray -func (v *IntSlice) MarshalJSONArray(enc *gojay.Encoder) { - for _, s := range *v { - enc.Int(s) - } -} - -// IsNil implements gojay's MarshalerJSONArray -func (v *IntSlice) IsNil() bool { - return *v == nil || len(*v) == 0 -} - -// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray -func (v *BoolSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { - var b bool - if err := dec.Bool(&b); err != nil { - return err - } - *v = append(*v, b) - return nil -} - -// MarshalJSONArray implements gojay's MarshalerJSONArray -func (v *BoolSlice) MarshalJSONArray(enc *gojay.Encoder) { - for _, s := range *v { - enc.Bool(s) - } -} - -// IsNil implements gojay's MarshalerJSONArray -func (v *BoolSlice) IsNil() bool { - return *v == nil || len(*v) == 0 -} - -// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray -func (v *StructSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { - var s = &A{} - if err := dec.Object(s); err != nil { - return err - } - *v = append(*v, s) - return nil -} - -// MarshalJSONArray implements gojay's MarshalerJSONArray -func (v *StructSlice) MarshalJSONArray(enc *gojay.Encoder) { - for _, s := range *v { - enc.Object(s) - } -} - -// IsNil implements gojay's MarshalerJSONArray -func (v *StructSlice) IsNil() bool { - return *v == nil || len(*v) == 0 -} - -// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray -func (v *SliceSlice) UnmarshalJSONArray(dec *gojay.Decoder) error { - var s = make(StrSlice, 0) - if err := dec.Array(&s); err != nil { - return err - } - *v = append(*v, &s) - return nil -} - -// MarshalJSONArray implements gojay's MarshalerJSONArray -func (v *SliceSlice) MarshalJSONArray(enc *gojay.Encoder) { - for _, s := range *v { - enc.Array(s) - } -} - -// IsNil implements gojay's MarshalerJSONArray -func (v *SliceSlice) IsNil() bool { - return *v == nil || len(*v) == 0 -} - -// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject -func (v *A) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { - switch k { - case "string": - return dec.String(&v.Str) - case "bool": - return dec.Bool(&v.Bool) - case "int": - return dec.Int(&v.Int) - case "int64": - return dec.Int64(&v.Int64) - case "int32": - return dec.Int32(&v.Int32) - case "int16": - return dec.Int16(&v.Int16) - case "int8": - return dec.Int8(&v.Int8) - case "uint64": - return dec.Uint64(&v.Uint64) - case "uint32": - return dec.Uint32(&v.Uint32) - case "uint16": - return dec.Uint16(&v.Uint16) - case "uint8": - return dec.Uint8(&v.Uint8) - case "bval": - if v.Bval == nil { - v.Bval = &B{} - } - return dec.Object(v.Bval) - case "arrval": - if v.Arrval == nil { - arr := make(StrSlice, 0) - v.Arrval = &arr - } - return dec.Array(v.Arrval) - } - return nil -} - -// NKeys returns the number of keys to unmarshal -func (v *A) NKeys() int { return 13 } - -// MarshalJSONObject implements gojay's MarshalerJSONObject -func (v *A) MarshalJSONObject(enc *gojay.Encoder) { - enc.StringKey("string", v.Str) - enc.BoolKey("bool", v.Bool) - enc.IntKey("int", v.Int) - enc.Int64Key("int64", v.Int64) - enc.Int32Key("int32", v.Int32) - enc.Int16Key("int16", v.Int16) - enc.Int8Key("int8", v.Int8) - enc.Uint64Key("uint64", v.Uint64) - enc.Uint32Key("uint32", v.Uint32) - enc.Uint16Key("uint16", v.Uint16) - enc.Uint8Key("uint8", v.Uint8) - enc.ObjectKey("bval", v.Bval) - enc.ArrayKey("arrval", v.Arrval) -} - -// IsNil returns wether the structure is nil value or not -func (v *A) IsNil() bool { return v == nil } - -// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject -func (v *B) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { - switch k { - case "str": - return dec.String(&v.Str) - case "bool": - return dec.Bool(&v.Bool) - case "int": - return dec.Int(&v.Int) - case "int64": - return dec.Int64(&v.Int64) - case "int32": - return dec.Int32(&v.Int32) - case "int16": - return dec.Int16(&v.Int16) - case "int8": - return dec.Int8(&v.Int8) - case "uint64": - return dec.Uint64(&v.Uint64) - case "uint32": - return dec.Uint32(&v.Uint32) - case "uint16": - return dec.Uint16(&v.Uint16) - case "uint8": - return dec.Uint8(&v.Uint8) - case "strPtr": - return dec.String(v.StrPtr) - case "boolPtr": - return dec.Bool(v.BoolPtr) - case "intPtr": - return dec.Int(v.IntPtr) - case "int64Ptr": - return dec.Int64(v.Int64Ptr) - case "int32Ptr": - return dec.Int32(v.Int32Ptr) - case "int16Ptr": - return dec.Int16(v.Int16Ptr) - case "int8Ptr": - return dec.Int8(v.Int8Ptr) - case "uint64Ptr": - return dec.Uint64(v.Uint64Ptr) - case "uint32Ptr": - return dec.Uint32(v.Uint32Ptr) - case "uint16Ptr": - return dec.Uint16(v.Uint16Ptr) - case "uint8PTr": - return dec.Uint8(v.Uint8PTr) - } - return nil -} - -// NKeys returns the number of keys to unmarshal -func (v *B) NKeys() int { return 22 } - -// MarshalJSONObject implements gojay's MarshalerJSONObject -func (v *B) MarshalJSONObject(enc *gojay.Encoder) { - enc.StringKey("str", v.Str) - enc.BoolKey("bool", v.Bool) - enc.IntKey("int", v.Int) - enc.Int64Key("int64", v.Int64) - enc.Int32Key("int32", v.Int32) - enc.Int16Key("int16", v.Int16) - enc.Int8Key("int8", v.Int8) - enc.Uint64Key("uint64", v.Uint64) - enc.Uint32Key("uint32", v.Uint32) - enc.Uint16Key("uint16", v.Uint16) - enc.Uint8Key("uint8", v.Uint8) - enc.StringKey("strPtr", *v.StrPtr) - enc.BoolKey("boolPtr", *v.BoolPtr) - enc.IntKey("intPtr", *v.IntPtr) - enc.Int64Key("int64Ptr", *v.Int64Ptr) - enc.Int32Key("int32Ptr", *v.Int32Ptr) - enc.Int16Key("int16Ptr", *v.Int16Ptr) - enc.Int8Key("int8Ptr", *v.Int8Ptr) - enc.Uint64Key("uint64Ptr", *v.Uint64Ptr) - enc.Uint32Key("uint32Ptr", *v.Uint32Ptr) - enc.Uint16Key("uint16Ptr", *v.Uint16Ptr) - enc.Uint8Key("uint8PTr", *v.Uint8PTr) -} - -// IsNil returns wether the structure is nil value or not -func (v *B) IsNil() bool { return v == nil } - -// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject -func (v MapStringInt) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { - var i int - if err := dec.Int(&i); err != nil { - return err - } - v[k] = i - return nil -} - -// NKeys returns the number of keys to unmarshal -func (v MapStringInt) NKeys() int { return 0 } - -// MarshalJSONObject implements gojay's MarshalerJSONObject -func (v MapStringInt) MarshalJSONObject(enc *gojay.Encoder) { - for k, s := range v { - enc.IntKey(k, s) - } -} - -// IsNil returns wether the structure is nil value or not -func (v MapStringInt) IsNil() bool { return v == nil || len(v) == 0 }