diff --git a/encode.go b/encode.go index e9206344..d32c76ee 100644 --- a/encode.go +++ b/encode.go @@ -221,15 +221,23 @@ func (e *encoder) structv(tag string, in reflect.Value, comment comments) { commentsArr := makeEmptyComments(len(fieldsIndex)) - if fIndex := getYamlMeta(in, fieldsIndex); fIndex.IsValid() { - meta := fIndex.Elem().Interface().(StructMeta) - fieldsIndex = meta.GetFieldsIndex() - commentsArr = meta.GetComments() + // ensure valid non nil struct meta before using + if fIndex := getYamlMeta(in, fieldsIndex); (fIndex.IsValid() && fIndex.Elem() != reflect.Value{}) { + meta, ok := fIndex.Elem().Interface().(StructMeta) + metaFieldsIndex := meta.GetFieldsIndex() + metaCommentsArr := meta.GetComments() + if ok && len(metaFieldsIndex) == len(metaCommentsArr) { + fieldsIndex = metaFieldsIndex + commentsArr = metaCommentsArr + } } e.mappingv(tag, comment, func() { processed := map[int]bool{} for i, info := range fieldsIndex { + if info.Key == yamlMeta { + continue + } var value reflect.Value if info.Inline == nil { value = in.Field(info.Num) diff --git a/go.sum b/go.sum new file mode 100644 index 00000000..d277f45c --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/structmeta_internal_test.go b/structmeta_internal_test.go index c14c55c7..f5dec6b4 100644 --- a/structmeta_internal_test.go +++ b/structmeta_internal_test.go @@ -30,6 +30,50 @@ var structMetaTests = []string{ "a: ant #ant\n# a\nb: #beeline\n c: cockroach #cockroach\n #c\n #d\n d: dragonfly\n #dragonfly\n", } +var structMetaNilTests = []struct { + expected string + test testStruct +}{ + { + "b:\n d: d\n c: c\na: a\n", + testStruct{ + A: "a", + B: smChildStruct{ + C: "c", + D: "d", + }, + }, + }, + { + "b:\n d: d\n c: c\na: a\n", + testStruct{ + A: "a", + B: smChildStruct{ + C: "c", + D: "d", + }, + Meta: StructMeta(&structMeta{nil, nil}), + }, + }, + { + "b:\n d: d\n c: c\na: a\n", + testStruct{ + A: "a", + B: smChildStruct{ + C: "c", + D: "d", + }, + Meta: StructMeta(&structMeta{ + []fieldInfo{{ + Key: "a", + Num: 2, + }}, + [][]comments{}, + }), + }, + }, +} + func (s *S) TestStructMeta(c *C) { for _, expected := range structMetaTests { c.Logf("test %s.", expected) @@ -43,3 +87,13 @@ func (s *S) TestStructMeta(c *C) { c.Assert(string(actual), Equals, expected) } } + +func (s *S) TestStructMetaNil(c *C) { + for _, in := range structMetaNilTests { + c.Logf("test %s", in.expected) + + actual, err := Marshal(in.test) + c.Assert(err, Equals, nil) + c.Assert(string(actual), Equals, in.expected) + } +}