Просмотр исходного кода

Add UnmarshalStrict returning error if yaml has fields that do not exist in structure

Witold Krecicki 9 лет назад
Родитель
Сommit
f8db564a0a
3 измененных файлов с 28 добавлено и 3 удалено
  1. 5 2
      decode.go
  2. 11 0
      decode_test.go
  3. 12 1
      yaml.go

+ 5 - 2
decode.go

@@ -190,6 +190,7 @@ type decoder struct {
 	aliases map[string]bool
 	mapType reflect.Type
 	terrors []string
+	strict  bool
 }
 
 var (
@@ -199,8 +200,8 @@ var (
 	ifaceType      = defaultMapType.Elem()
 )
 
-func newDecoder() *decoder {
-	d := &decoder{mapType: defaultMapType}
+func newDecoder(strict bool) *decoder {
+	d := &decoder{mapType: defaultMapType, strict: strict}
 	d.aliases = make(map[string]bool)
 	return d
 }
@@ -639,6 +640,8 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
 			value := reflect.New(elemType).Elem()
 			d.unmarshal(n.children[i+1], value)
 			inlineMap.SetMapIndex(name, value)
+		} else if d.strict {
+			d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in struct %s", n.line+1, name.String(), out.Type()))
 		}
 	}
 	return true

+ 11 - 0
decode_test.go

@@ -968,6 +968,17 @@ func (s *S) TestUnmarshalSliceOnPreset(c *C) {
 	c.Assert(v.A, DeepEquals, []int{2})
 }
 
+func (s *S) TestUnmarshalStrict(c *C) {
+	v := struct{ A, B int }{}
+
+	err := yaml.UnmarshalStrict([]byte("a: 1\nb: 2"), &v)
+	c.Check(err, IsNil)
+	err = yaml.Unmarshal([]byte("a: 1\nb: 2\nc: 3"), &v)
+	c.Check(err, IsNil)
+	err = yaml.UnmarshalStrict([]byte("a: 1\nb: 2\nc: 3"), &v)
+	c.Check(err, ErrorMatches, "yaml: unmarshal errors:\n  line 1: field c not found in struct struct { A int; B int }")
+}
+
 //var data []byte
 //func init() {
 //	var err error

+ 12 - 1
yaml.go

@@ -77,8 +77,19 @@ type Marshaler interface {
 // supported tag options.
 //
 func Unmarshal(in []byte, out interface{}) (err error) {
+	return unmarshal(in, out, false)
+}
+
+// UnmarshalStrict is like Unmarshal except that any fields that are found
+// in the data that do not have corresponding struct members will result in
+// an error.
+func UnmarshalStrict(in []byte, out interface{}) (err error) {
+	return unmarshal(in, out, true)
+}
+
+func unmarshal(in []byte, out interface{}, strict bool) (err error) {
 	defer handleErr(&err)
-	d := newDecoder()
+	d := newDecoder(strict)
 	p := newParser(in)
 	defer p.destroy()
 	node := p.parse()