gojay

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

commit a667dd76ca13c376331e6d9ec2d8746d085ff985
parent af36826393b902b5c558dc49073c249e4fa2ebfe
Author: francoispqt <francois@parquet.ninja>
Date:   Thu, 31 May 2018 22:29:47 +0800

add struct marshaling in generatr

Diffstat:
Mgojay/gen_struct_marshal.go | 188++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mgojay/tests/basic_structs_gojay.go | 5+++--
2 files changed, 126 insertions(+), 67 deletions(-)

diff --git a/gojay/gen_struct_marshal.go b/gojay/gen_struct_marshal.go @@ -1,11 +1,15 @@ package main import ( + "errors" "go/ast" "html/template" "log" "os" + "reflect" "strings" + + "github.com/davecgh/go-spew/spew" ) var structMarshalDefTpl *template.Template @@ -13,6 +17,7 @@ var structMarshalStringTpl *template.Template var structMarshalIntTpl *template.Template var structMarshalUintTpl *template.Template var structMarshalBoolTpl *template.Template +var structMarshalStructTpl *template.Template var structIsNilTpl *template.Template @@ -24,7 +29,7 @@ func (v *{{.StructName}}) IsNil() bool { return v == nil } func init() { t, err := template.New("structUnmarshalDef"). Parse("\n// MarshalJSONObject implements gojay's MarshalerJSONObject" + - "\nfunc (v *{{.StructName}}) MarshalJSONOject(enc *gojay.Encoder) {\n", + "\nfunc (v *{{.StructName}}) MarshalJSONObject(enc *gojay.Encoder) {\n", ) if err != nil { log.Fatal(err) @@ -59,6 +64,13 @@ func init() { } structMarshalBoolTpl = t + t, err = template.New("structMarshalCaseStruct"). + Parse("\tenc.ObjectKey(\"{{.Key}}\", v.{{.Field}})\n") + if err != nil { + log.Fatal(err) + } + structMarshalStructTpl = t + t, err = template.New("structMarhalIsNil"). Parse(isNilMethod) if err != nil { @@ -91,74 +103,25 @@ func (v *vis) structGenMarshalObj(f *os.File, n string, s *ast.StructType) (int, for _, field := range s.Fields.List { switch t := field.Type.(type) { case *ast.Ident: - switch t.String() { - case "string": - err = v.structMarshalString(f, field) - if err != nil { - return 0, err - } - keys++ - case "bool": - err = v.structMarshalBool(f, field) - if err != nil { - return 0, err - } - keys++ - case "int": - err = v.structMarshalInt(f, field, "") - if err != nil { - return 0, err - } - keys++ - case "int64": - err = v.structMarshalInt(f, field, "64") - if err != nil { - return 0, err - } - keys++ - case "int32": - err = v.structMarshalInt(f, field, "32") - if err != nil { - return 0, err - } - keys++ - case "int16": - err = v.structMarshalInt(f, field, "16") - if err != nil { - return 0, err - } - keys++ - case "int8": - err = v.structMarshalInt(f, field, "8") - if err != nil { - return 0, err - } - keys++ - case "uint64": - err = v.structMarshalUint(f, field, "64") - if err != nil { - return 0, err - } - keys++ - case "uint32": - err = v.structMarshalUint(f, field, "32") - if err != nil { - return 0, err - } - keys++ - case "uint16": - err = v.structMarshalUint(f, field, "16") - if err != nil { - return 0, err - } - keys++ - case "uint8": - err = v.structMarshalUint(f, field, "8") + var err error + keys, err = v.structGenMarshalIdent(f, field, t, keys) + if err != nil { + return 0, err + } + case *ast.StarExpr: + switch ptrExp := t.X.(type) { + case *ast.Ident: + var err error + keys, err = v.structGenMarshalIdent(f, field, ptrExp, keys) if err != nil { return 0, err } - keys++ + default: + spew.Println(reflect.TypeOf(ptrExp)) + spew.Println(ptrExp) } + default: + spew.Println(t) } } } @@ -169,6 +132,89 @@ func (v *vis) structGenMarshalObj(f *os.File, n string, s *ast.StructType) (int, return keys, nil } +func (v *vis) structGenMarshalIdent(f *os.File, field *ast.Field, i *ast.Ident, keys int) (int, error) { + switch i.String() { + case "string": + var err = v.structMarshalString(f, field) + if err != nil { + return 0, err + } + keys++ + case "bool": + var err = v.structMarshalBool(f, field) + if err != nil { + return 0, err + } + keys++ + case "int": + var err = v.structMarshalInt(f, field, "") + if err != nil { + return 0, err + } + keys++ + case "int64": + var err = v.structMarshalInt(f, field, "64") + if err != nil { + return 0, err + } + keys++ + case "int32": + var err = v.structMarshalInt(f, field, "32") + if err != nil { + return 0, err + } + keys++ + case "int16": + var err = v.structMarshalInt(f, field, "16") + if err != nil { + return 0, err + } + keys++ + case "int8": + var err = v.structMarshalInt(f, field, "8") + if err != nil { + return 0, err + } + keys++ + case "uint64": + var err = v.structMarshalUint(f, field, "64") + if err != nil { + return 0, err + } + keys++ + case "uint32": + var err = v.structMarshalUint(f, field, "32") + if err != nil { + return 0, err + } + keys++ + case "uint16": + var err = v.structMarshalUint(f, field, "16") + if err != nil { + return 0, err + } + keys++ + case "uint8": + var err = v.structMarshalUint(f, field, "8") + if err != nil { + return 0, err + } + keys++ + default: + switch t := i.Obj.Decl.(type) { + case *ast.TypeSpec: + var err = v.structMarshalStruct(f, field, t) + if err != nil { + return 0, err + } + keys++ + default: + return 0, errors.New("could not determine what to do with type " + i.String()) + } + } + return keys, nil +} + func (v *vis) structMarshalString(f *os.File, field *ast.Field) error { key := field.Names[0].String() err := structMarshalStringTpl.Execute(f, struct { @@ -218,3 +264,15 @@ func (v *vis) structMarshalUint(f *os.File, field *ast.Field, intLen string) err } return nil } + +func (v *vis) structMarshalStruct(f *os.File, field *ast.Field, st *ast.TypeSpec) error { + key := field.Names[0].String() + var err = structMarshalStructTpl.Execute(f, struct { + Key string + Field string + }{strings.ToLower(key), key}) + if err != nil { + return err + } + return nil +} diff --git a/gojay/tests/basic_structs_gojay.go b/gojay/tests/basic_structs_gojay.go @@ -40,7 +40,7 @@ func (v *A) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { func (v *A) NKeys() int { return 12 } // MarshalJSONObject implements gojay's MarshalerJSONObject -func (v *A) MarshalJSONOject(enc *gojay.Encoder) { +func (v *A) MarshalJSONObject(enc *gojay.Encoder) { enc.StringKey("str", v.Str) enc.BoolKey("bool", v.Bool) enc.IntKey("int", v.Int) @@ -52,6 +52,7 @@ func (v *A) MarshalJSONOject(enc *gojay.Encoder) { enc.Uint32Key("uint32", v.Uint32) enc.Uint16Key("uint16", v.Uint16) enc.Uint8Key("uint8", v.Uint8) + enc.ObjectKey("bval", v.Bval) } // IsNil returns wether the structure is nil value or not @@ -90,7 +91,7 @@ func (v *B) UnmarshalJSONObject(dec *gojay.Decoder, k string) error { func (v *B) NKeys() int { return 11 } // MarshalJSONObject implements gojay's MarshalerJSONObject -func (v *B) MarshalJSONOject(enc *gojay.Encoder) { +func (v *B) MarshalJSONObject(enc *gojay.Encoder) { enc.StringKey("str", v.Str) enc.BoolKey("bool", v.Bool) enc.IntKey("int", v.Int)