From c63cf99c78d24fe8f5484aab05defd6daeb89f12 Mon Sep 17 00:00:00 2001 From: Aleksandr Petrukhin Date: Tue, 29 May 2018 16:19:21 +0000 Subject: [PATCH 1/3] [Generator] implement DisallowUnknownFields from go 1.10 --- bootstrap/bootstrap.go | 12 ++++++++---- easyjson/main.go | 26 ++++++++++++++------------ gen/decoder.go | 10 +++++++++- gen/generator.go | 12 +++++++++--- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go index 3c20e09..95e5d1e 100644 --- a/bootstrap/bootstrap.go +++ b/bootstrap/bootstrap.go @@ -22,10 +22,11 @@ type Generator struct { PkgPath, PkgName string Types []string - NoStdMarshalers bool - SnakeCase bool - LowerCamelCase bool - OmitEmpty bool + NoStdMarshalers bool + SnakeCase bool + LowerCamelCase bool + OmitEmpty bool + DisallowUnknownFields bool OutName string BuildTags string @@ -120,6 +121,9 @@ func (g *Generator) writeMain() (path string, err error) { if g.NoStdMarshalers { fmt.Fprintln(f, " g.NoStdMarshalers()") } + if g.DisallowUnknownFields { + fmt.Fprintln(f, " g.DisallowUnknownFields()") + } sort.Strings(g.Types) for _, v := range g.Types { diff --git a/easyjson/main.go b/easyjson/main.go index 1cd30bb..df180ea 100644 --- a/easyjson/main.go +++ b/easyjson/main.go @@ -27,6 +27,7 @@ var stubs = flag.Bool("stubs", false, "only generate stubs for marshaler/unmarsh var noformat = flag.Bool("noformat", false, "do not run 'gofmt -w' on output file") var specifiedName = flag.String("output_filename", "", "specify the filename of the output") var processPkg = flag.Bool("pkg", false, "process the whole package instead of just the given file") +var disallowUnknownFields = flag.Bool("disallow_unknown_fields", false, "return error if any unknown field in json found") func generate(fname string) (err error) { fInfo, err := os.Stat(fname) @@ -60,18 +61,19 @@ func generate(fname string) (err error) { } g := bootstrap.Generator{ - BuildTags: trimmedBuildTags, - PkgPath: p.PkgPath, - PkgName: p.PkgName, - Types: p.StructNames, - SnakeCase: *snakeCase, - LowerCamelCase: *lowerCamelCase, - NoStdMarshalers: *noStdMarshalers, - OmitEmpty: *omitEmpty, - LeaveTemps: *leaveTemps, - OutName: outName, - StubsOnly: *stubs, - NoFormat: *noformat, + BuildTags: trimmedBuildTags, + PkgPath: p.PkgPath, + PkgName: p.PkgName, + Types: p.StructNames, + SnakeCase: *snakeCase, + LowerCamelCase: *lowerCamelCase, + NoStdMarshalers: *noStdMarshalers, + DisallowUnknownFields: *disallowUnknownFields, + OmitEmpty: *omitEmpty, + LeaveTemps: *leaveTemps, + OutName: outName, + StubsOnly: *stubs, + NoFormat: *noformat, } if err := g.Run(); err != nil { diff --git a/gen/decoder.go b/gen/decoder.go index 3c8f8f8..5dc1249 100644 --- a/gen/decoder.go +++ b/gen/decoder.go @@ -461,7 +461,15 @@ func (g *Generator) genStructDecoder(t reflect.Type) error { } fmt.Fprintln(g.out, " default:") - fmt.Fprintln(g.out, " in.SkipRecursive()") + if g.disallowUnknownFields { + fmt.Fprintln(g.out, ` in.AddError(&jlexer.LexerError{ + Offset: in.GetPos(), + Reason: "unknown field", + Data: key, + })`) + } else { + fmt.Fprintln(g.out, " in.SkipRecursive()") + } fmt.Fprintln(g.out, " }") fmt.Fprintln(g.out, " in.WantComma()") fmt.Fprintln(g.out, " }") diff --git a/gen/generator.go b/gen/generator.go index 4f1eb04..a34a852 100644 --- a/gen/generator.go +++ b/gen/generator.go @@ -33,9 +33,10 @@ type Generator struct { varCounter int - noStdMarshalers bool - omitEmpty bool - fieldNamer FieldNamer + noStdMarshalers bool + omitEmpty bool + disallowUnknownFields bool + fieldNamer FieldNamer // package path to local alias map for tracking imports imports map[string]string @@ -110,6 +111,11 @@ func (g *Generator) NoStdMarshalers() { g.noStdMarshalers = true } +// DisallowUnknownFields instructs not to skip unknown fields in json and return error. +func (g *Generator) DisallowUnknownFields() { + g.disallowUnknownFields = true +} + // OmitEmpty triggers `json=",omitempty"` behaviour by default. func (g *Generator) OmitEmpty() { g.omitEmpty = true From 31e0226908ff016d8ba91a190809827975248941 Mon Sep 17 00:00:00 2001 From: Aleksandr Petrukhin Date: Tue, 29 May 2018 16:32:28 +0000 Subject: [PATCH 2/3] [Tests] add tests for disallow_unknown_fields --- .gitignore | 1 + Makefile | 1 + README.md | 2 ++ tests/basic_test.go | 8 ++++++++ tests/disallow_unknown.go | 8 ++++++++ 5 files changed, 20 insertions(+) create mode 100644 tests/disallow_unknown.go diff --git a/.gitignore b/.gitignore index db8c66e..26156fb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *_easyjson.go *.iml .idea +*.swp diff --git a/Makefile b/Makefile index 49c80f3..7717c1e 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,7 @@ generate: root build .root/bin/easyjson .root/src/$(PKG)/tests/named_type.go .root/bin/easyjson .root/src/$(PKG)/tests/custom_map_key_type.go .root/bin/easyjson .root/src/$(PKG)/tests/embedded_type.go + .root/bin/easyjson -disallow_unknown_fields .root/src/$(PKG)/tests/disallow_unknown.go test: generate root go test \ diff --git a/README.md b/README.md index 9366e3f..b59d3ad 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ Usage of easyjson: use lowerCamelCase instead of CamelCase by default -stubs only generate stubs for marshaler/unmarshaler funcs + -disallow_unknown_fields + return error if some unknown field in json occured ``` Using `-all` will generate marshalers/unmarshalers for all Go structs in the diff --git a/tests/basic_test.go b/tests/basic_test.go index 28f0fdf..ab166f3 100644 --- a/tests/basic_test.go +++ b/tests/basic_test.go @@ -232,3 +232,11 @@ func TestUnmarshalStructWithEmbeddedPtrStruct(t *testing.T) { t.Errorf("easyjson.Unmarshal() = %#v; want %#v", s, structWithInterfaceValueFilled) } } + +func TestDisallowUnknown(t *testing.T) { + var d DisallowUnknown + err := easyjson.Unmarshal([]byte(disallowUnknownString), &d) + if err == nil { + t.Error("want error, got nil") + } +} diff --git a/tests/disallow_unknown.go b/tests/disallow_unknown.go new file mode 100644 index 0000000..5b884c6 --- /dev/null +++ b/tests/disallow_unknown.go @@ -0,0 +1,8 @@ +package tests + +//easyjson:json +type DisallowUnknown struct { + FieldOne string `json:"field_one"` +} + +var disallowUnknownString = `{"field_one": "one", "field_two": "two"}` From 1df2e963608a01ba264fc317ba44cae08db2dd06 Mon Sep 17 00:00:00 2001 From: Aleksandr Petrukhin Date: Tue, 29 May 2018 16:34:20 +0000 Subject: [PATCH 3/3] [README] fix --- README.md | 2 +- easyjson/main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b59d3ad..7fd7686 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Usage of easyjson: -stubs only generate stubs for marshaler/unmarshaler funcs -disallow_unknown_fields - return error if some unknown field in json occured + return error if some unknown field in json appeared ``` Using `-all` will generate marshalers/unmarshalers for all Go structs in the diff --git a/easyjson/main.go b/easyjson/main.go index df180ea..d4035f7 100644 --- a/easyjson/main.go +++ b/easyjson/main.go @@ -27,7 +27,7 @@ var stubs = flag.Bool("stubs", false, "only generate stubs for marshaler/unmarsh var noformat = flag.Bool("noformat", false, "do not run 'gofmt -w' on output file") var specifiedName = flag.String("output_filename", "", "specify the filename of the output") var processPkg = flag.Bool("pkg", false, "process the whole package instead of just the given file") -var disallowUnknownFields = flag.Bool("disallow_unknown_fields", false, "return error if any unknown field in json found") +var disallowUnknownFields = flag.Bool("disallow_unknown_fields", false, "return error if any unknown field in json appeared") func generate(fname string) (err error) { fInfo, err := os.Stat(fname)