diff --git a/decode.go b/decode.go index 3718e01e..dd739d15 100644 --- a/decode.go +++ b/decode.go @@ -529,7 +529,6 @@ func (d *Decoder) decodeStruct(dst reflect.Value, src ast.Node) error { return nil } structType := dst.Type() - structValue := reflect.New(structType) structFieldMap, err := structFieldMap(structType) if err != nil { return errors.Wrapf(err, "failed to create struct field map") @@ -555,7 +554,7 @@ func (d *Decoder) decodeStruct(dst reflect.Value, src ast.Node) error { } structField := structFieldMap[field.Name] if structField.IsInline { - fieldValue := structValue.Elem().FieldByName(field.Name) + fieldValue := dst.FieldByName(field.Name) if !fieldValue.CanSet() { return xerrors.Errorf("cannot set embedded type as unexported field %s.%s", field.PkgPath, field.Name) } @@ -593,7 +592,7 @@ func (d *Decoder) decodeStruct(dst reflect.Value, src ast.Node) error { continue } delete(unknownFields, structField.RenderName) - fieldValue := structValue.Elem().FieldByName(field.Name) + fieldValue := dst.FieldByName(field.Name) if fieldValue.Type().Kind() == reflect.Ptr && src.Type() == ast.NullType { // set nil value to pointer fieldValue.Set(reflect.Zero(fieldValue.Type())) @@ -617,7 +616,7 @@ func (d *Decoder) decodeStruct(dst reflect.Value, src ast.Node) error { fieldValue.Set(d.castToAssignableValue(newFieldValue, fieldValue.Type())) } if d.validator != nil { - if err := d.validator.Struct(structValue.Interface()); err != nil { + if err := d.validator.Struct(dst.Interface()); err != nil { ev := reflect.ValueOf(err) if ev.Type().Kind() == reflect.Slice { for i := 0; i < ev.Len(); i++ { @@ -641,7 +640,6 @@ func (d *Decoder) decodeStruct(dst reflect.Value, src ast.Node) error { return errors.ErrSyntax(fmt.Sprintf(`unknown field "%s"`, key), node.GetToken()) } } - dst.Set(structValue.Elem()) if foundErr != nil { return errors.Wrapf(foundErr, "failed to decode value") } diff --git a/decode_test.go b/decode_test.go index 2d882fb2..e42ada59 100644 --- a/decode_test.go +++ b/decode_test.go @@ -1194,6 +1194,35 @@ b_yaml: b_yaml_value } } +func TestDecoder_DefaultValues(t *testing.T) { + v := struct { + A string `yaml:"a"` + B string `yaml:"b"` + c string // private + }{ + B: "defaultBValue", + c: "defaultCValue", + } + + const src = `--- +a: a_value +` + if err := yaml.NewDecoder(strings.NewReader(src)).Decode(&v); err != nil { + t.Fatalf(`parsing should succeed: %s`, err) + } + if v.A != "a_value" { + t.Fatalf("v.A should be `a_value`, got `%s`", v.A) + } + + if v.B != "defaultBValue" { + t.Fatalf("v.B should be `defaultValue`, got `%s`", v.B) + } + + if v.c != "defaultCValue" { + t.Fatalf("v.c should be `defaultCValue`, got `%s`", v.c) + } +} + func Example_YAMLTags() { yml := `--- foo: 1