commit af36826393b902b5c558dc49073c249e4fa2ebfe
parent ed06be23fa1713f994603eb28bfe7b59f9ae0f2b
Author: francoispqt <francois@parquet.ninja>
Date: Thu, 31 May 2018 00:10:15 +0800
add struc field unmarshaling clean code
Diffstat:
4 files changed, 151 insertions(+), 75 deletions(-)
diff --git a/gojay/gen_struct_unmarshal.go b/gojay/gen_struct_unmarshal.go
@@ -1,11 +1,15 @@
package main
import (
+ "errors"
"go/ast"
"html/template"
"log"
"os"
+ "reflect"
"strings"
+
+ "github.com/davecgh/go-spew/spew"
)
var structUnmarshalDefTpl *template.Template
@@ -14,6 +18,7 @@ var structUnmarshalStringTpl *template.Template
var structUnmarshalIntTpl *template.Template
var structUnmarshalUintTpl *template.Template
var structUnmarshalBoolTpl *template.Template
+var structUnmarshalStructTpl *template.Template
var structNKeysTpl *template.Template
@@ -27,8 +32,8 @@ var structUnmarshalClose = []byte("\treturn nil\n}\n")
func init() {
t, err := template.New("structUnmarshalDef").
- Parse("\n// UnmarshalJSONOject implements gojay's UnmarshalerJSONObject" +
- "\nfunc (v *{{.StructName}}) UnmarshalJSONOject(dec *gojay.Decoder, k string) error {\n",
+ Parse("\n// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject" +
+ "\nfunc (v *{{.StructName}}) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {\n",
)
if err != nil {
log.Fatal(err)
@@ -49,33 +54,46 @@ func init() {
}
structUnmarshalStringTpl = t
- t, err = template.New("structUnmarshalCaseString").
+ t, err = template.New("structUnmarshalCaseInt").
Parse("\t\treturn dec.Int{{.IntLen}}(&v.{{.Field}})\n")
if err != nil {
log.Fatal(err)
}
structUnmarshalIntTpl = t
- t, err = template.New("structUnmarshalCaseString").
+ t, err = template.New("structUnmarshalCaseUint").
Parse("\t\treturn dec.Uint{{.IntLen}}(&v.{{.Field}})\n")
if err != nil {
log.Fatal(err)
}
structUnmarshalUintTpl = t
- t, err = template.New("structUnmarshalCaseString").
+ t, err = template.New("structUnmarshalCaseBool").
Parse("\t\treturn dec.Bool(&v.{{.Field}})\n")
if err != nil {
log.Fatal(err)
}
structUnmarshalBoolTpl = t
+ t, err = template.New("structUnmarshalCaseStruct").
+ Parse(
+ ` if v.{{.Field}} == nil {
+ v.{{.Field}} = &{{.StructName}}{}
+ }
+ dec.Object(v.{{.Field}})
+`)
+ if err != nil {
+ log.Fatal(err)
+ }
+ structUnmarshalStructTpl = t
+
t, err = template.New("structUnmarshalNKeys").
Parse(nKeysMethod)
if err != nil {
log.Fatal(err)
}
structNKeysTpl = t
+
}
func (v *vis) structGenNKeys(f *os.File, n string, count int) error {
@@ -107,74 +125,25 @@ func (v *vis) structGenUnmarshalObj(f *os.File, n string, s *ast.StructType) (in
for _, field := range s.Fields.List {
switch t := field.Type.(type) {
case *ast.Ident:
- switch t.String() {
- case "string":
- err = v.structUnmarshalString(f, field)
- if err != nil {
- return 0, err
- }
- keys++
- case "bool":
- err = v.structUnmarshalBool(f, field)
- if err != nil {
- return 0, err
- }
- keys++
- case "int":
- err = v.structUnmarshalInt(f, field, "")
- if err != nil {
- return 0, err
- }
- keys++
- case "int64":
- err = v.structUnmarshalInt(f, field, "64")
- if err != nil {
- return 0, err
- }
- keys++
- case "int32":
- err = v.structUnmarshalInt(f, field, "32")
- if err != nil {
- return 0, err
- }
- keys++
- case "int16":
- err = v.structUnmarshalInt(f, field, "16")
- if err != nil {
- return 0, err
- }
- keys++
- case "int8":
- err = v.structUnmarshalInt(f, field, "8")
- if err != nil {
- return 0, err
- }
- keys++
- case "uint64":
- err = v.structUnmarshalUint(f, field, "64")
- if err != nil {
- return 0, err
- }
- keys++
- case "uint32":
- err = v.structUnmarshalUint(f, field, "32")
- if err != nil {
- return 0, err
- }
- keys++
- case "uint16":
- err = v.structUnmarshalUint(f, field, "16")
- if err != nil {
- return 0, err
- }
- keys++
- case "uint8":
- err = v.structUnmarshalUint(f, field, "8")
+ var err error
+ keys, err = v.structGenUnmarshalIdent(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.structGenUnmarshalIdent(f, field, ptrExp, keys)
if err != nil {
return 0, err
}
- keys++
+ default:
+ spew.Println(reflect.TypeOf(ptrExp))
+ spew.Println(ptrExp)
}
+ default:
+ spew.Println(t)
}
}
// close switch statement
@@ -187,6 +156,89 @@ func (v *vis) structGenUnmarshalObj(f *os.File, n string, s *ast.StructType) (in
return keys, nil
}
+func (v *vis) structGenUnmarshalIdent(f *os.File, field *ast.Field, i *ast.Ident, keys int) (int, error) {
+ switch i.String() {
+ case "string":
+ var err = v.structUnmarshalString(f, field)
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "bool":
+ var err = v.structUnmarshalBool(f, field)
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "int":
+ var err = v.structUnmarshalInt(f, field, "")
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "int64":
+ var err = v.structUnmarshalInt(f, field, "64")
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "int32":
+ var err = v.structUnmarshalInt(f, field, "32")
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "int16":
+ var err = v.structUnmarshalInt(f, field, "16")
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "int8":
+ var err = v.structUnmarshalInt(f, field, "8")
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "uint64":
+ var err = v.structUnmarshalUint(f, field, "64")
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "uint32":
+ var err = v.structUnmarshalUint(f, field, "32")
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "uint16":
+ var err = v.structUnmarshalUint(f, field, "16")
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ case "uint8":
+ var err = v.structUnmarshalUint(f, field, "8")
+ if err != nil {
+ return 0, err
+ }
+ keys++
+ default:
+ switch t := i.Obj.Decl.(type) {
+ case *ast.TypeSpec:
+ var err = v.structUnmarshalStruct(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) structUnmarshalString(f *os.File, field *ast.Field) error {
key := field.Names[0].String()
err := structUnmarshalCaseTpl.Execute(f, struct {
@@ -256,3 +308,21 @@ func (v *vis) structUnmarshalUint(f *os.File, field *ast.Field, intLen string) e
}
return nil
}
+
+func (v *vis) structUnmarshalStruct(f *os.File, field *ast.Field, st *ast.TypeSpec) error {
+ key := field.Names[0].String()
+ err := structUnmarshalCaseTpl.Execute(f, struct {
+ Key string
+ }{strings.ToLower(key)})
+ if err != nil {
+ return err
+ }
+ err = structUnmarshalStructTpl.Execute(f, struct {
+ Field string
+ StructName string
+ }{key, st.Name.String()})
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/gojay/gojay b/gojay/gojay
Binary files differ.
diff --git a/gojay/tests/basic_structs.go b/gojay/tests/basic_structs.go
@@ -13,6 +13,7 @@ type A struct {
Uint32 uint32
Uint16 uint16
Uint8 uint8
+ Bval *B
}
//gojay:json
diff --git a/gojay/tests/basic_structs_gojay.go b/gojay/tests/basic_structs_gojay.go
@@ -1,9 +1,9 @@
-package tests
+package tests
import "github.com/francoispqt/gojay"
-// UnmarshalJSONOject implements gojay's UnmarshalerJSONObject
-func (v *A) UnmarshalJSONOject(dec *gojay.Decoder, k string) error {
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (v *A) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
switch k {
case "str":
return dec.String(&v.Str)
@@ -27,12 +27,17 @@ func (v *A) UnmarshalJSONOject(dec *gojay.Decoder, k string) error {
return dec.Uint16(&v.Uint16)
case "uint8":
return dec.Uint8(&v.Uint8)
+ case "bval":
+ if v.Bval == nil {
+ v.Bval = &B{}
+ }
+ dec.Object(v.Bval)
}
return nil
}
// NKeys returns the number of keys to unmarshal
-func (v *A) NKeys() int { return 11 }
+func (v *A) NKeys() int { return 12 }
// MarshalJSONObject implements gojay's MarshalerJSONObject
func (v *A) MarshalJSONOject(enc *gojay.Encoder) {
@@ -52,8 +57,8 @@ func (v *A) MarshalJSONOject(enc *gojay.Encoder) {
// IsNil returns wether the structure is nil value or not
func (v *A) IsNil() bool { return v == nil }
-// UnmarshalJSONOject implements gojay's UnmarshalerJSONObject
-func (v *B) UnmarshalJSONOject(dec *gojay.Decoder, k string) error {
+// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
+func (v *B) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
switch k {
case "str":
return dec.String(&v.Str)