From 4eca6085cbc14a3d94104e54fc566fbda0d047fb Mon Sep 17 00:00:00 2001 From: Ben Kalman Date: Tue, 20 Dec 2016 16:47:49 -0800 Subject: [PATCH] Allow skipping invalid fields when marshalling (#2967) Currently unexported fields refuse to marshal or unmarshal, even if they're told to skip. Now, they can be skipped. By default, they are still errors. --- go/marshal/decode.go | 4 ++-- go/marshal/decode_test.go | 15 +++++++++++++++ go/marshal/encode.go | 10 +++++----- go/marshal/encode_test.go | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/go/marshal/decode.go b/go/marshal/decode.go index 058e5d4557..2c05d2b449 100644 --- a/go/marshal/decode.go +++ b/go/marshal/decode.go @@ -254,13 +254,13 @@ func structDecoder(t reflect.Type) decoderFunc { fields := make([]decField, 0, t.NumField()) for i := 0; i < t.NumField(); i++ { f := t.Field(i) - validateField(f, t) - tags := getTags(f) if tags.skip { continue } + validateField(f, t) + fields = append(fields, decField{ name: tags.name, decoder: typeDecoder(f.Type, tags), diff --git a/go/marshal/decode_test.go b/go/marshal/decode_test.go index 7c4489cd87..3d62ad270a 100644 --- a/go/marshal/decode_test.go +++ b/go/marshal/decode_test.go @@ -813,3 +813,18 @@ func TestDecodeOriginalReceiveTypeError(t *testing.T) { assert.Error(err) assert.Equal(`Cannot unmarshal struct S {} into Go value of type marshal.S, field with tag "original" must have type Struct`, err.Error()) } + +func TestDecodeCanSkipUnexportedField(t *testing.T) { + assert := assert.New(t) + + type S struct { + Abc int + notExported bool `noms:"-"` + } + var s S + err := Unmarshal(types.NewStruct("S", types.StructData{ + "abc": types.Number(42), + }), &s) + assert.NoError(err) + assert.Equal(S{42, false}, s) +} diff --git a/go/marshal/encode.go b/go/marshal/encode.go index 24d213044b..1a20825939 100644 --- a/go/marshal/encode.go +++ b/go/marshal/encode.go @@ -356,17 +356,17 @@ func typeFields(t reflect.Type, parentStructTypes []reflect.Type) (fields fieldS canComputeStructType := true for i := 0; i < t.NumField(); i++ { f := t.Field(i) + tags := getTags(f) + if tags.skip { + continue + } + validateField(f, t) nt := nomsType(f.Type, parentStructTypes) if nt == nil { canComputeStructType = false } - tags := getTags(f) - if tags.skip { - continue - } - if tags.omitEmpty { canComputeStructType = false } diff --git a/go/marshal/encode_test.go b/go/marshal/encode_test.go index 45eb69fa33..8184873600 100644 --- a/go/marshal/encode_test.go +++ b/go/marshal/encode_test.go @@ -632,6 +632,21 @@ func TestInvalidTag(t *testing.T) { assert.Equal(t, `Unrecognized tag: omitEmpty`, err.Error()) } +func TestEncodeCanSkipUnexportedField(t *testing.T) { + assert := assert.New(t) + + type S struct { + Abc int + notExported bool `noms:"-"` + } + s := S{42, true} + v, err := Marshal(s) + assert.NoError(err) + assert.True(types.NewStruct("S", types.StructData{ + "abc": types.Number(42), + }).Equals(v)) +} + type TestInterface interface { M() }