Repository: goccy/go-yaml (go)

Issue:
Decoder overrides defaults with null values
**Is your feature request related to a problem? Please describe.**

The decoder overrides the default values of a nested struct with zero-initialised value.

```go
package main

import (
	"fmt"
	//"gopkg.in/yaml.v3"
	"strings"
	"github.com/goccy/go-yaml"
)

type Default struct {
	Key string `yaml:"key"`
}

type Test struct {
	First    string  `yaml:"first"`
	Defaults Default `yaml:"second"`
}

func main() {
	yml := `
first: "Test"
second:
  # Just want to document the fields of the nested struct
#  key: "Value from YAML"
`

	test := Test{Defaults: Default{Key: "My default Value"}}
	d := yaml.NewDecoder(strings.NewReader(yml))
	if err := d.Decode(&test); err != nil {
		fmt.Println("cannot decode: ", err)
		return
	}

	fmt.Printf("%#v", test)
}
```

This prints with **go-yaml** `main.Test{First:"Test", Defaults:main.Default{Key:""}}`  while with..
**yaml.v3** it prints `main.Test{First:"Test", Defaults:main.Default{Key:"My default Value"}}`.

**Describe the solution you'd like**

It might be desirable to stick with the current behaviour by default (as it might break some applications that depend on it, I guess!), however, it would be nice if there would be an option to control this, something like `yaml.IgnoreNullValues()`.

Pull request description:
Preserve defaults for zero initialised structs as well
Before submitting your PR, please confirm the following.

- [x] Describe the purpose for which you created this PR. 
With https://github.com/goccy/go-yaml/pull/260, `go-yaml` already supports preserving default values for nested structs when decoding, however, there's one use case that was missed.

```yaml
---
first: "Test"
nested: # The decoder will always zero-initialise this nested struct and override the defaults
  # Just some comment here
#  val: "default"
```

- [x] Create test code that corresponds to the modification

fixes #441 

Patch:
diff --git a/decode.go b/decode.go
index 72af5e2..04b94bc 100644
--- a/decode.go
+++ b/decode.go
@@ -989,18 +989,22 @@ func (d *Decoder) createDecodedNewValue(
 			return newValue, nil
 		}
 	}
+	var newValue reflect.Value
 	if node.Type() == ast.NullType {
-		return reflect.Zero(typ), nil
+		newValue = reflect.New(typ).Elem()
+	} else {
+		newValue = d.createDecodableValue(typ)
 	}
-	newValue := d.createDecodableValue(typ)
 	for defaultVal.Kind() == reflect.Ptr {
 		defaultVal = defaultVal.Elem()
 	}
 	if defaultVal.IsValid() && defaultVal.Type().AssignableTo(newValue.Type()) {
 		newValue.Set(defaultVal)
 	}
-	if err := d.decodeValue(ctx, newValue, node); err != nil {
-		return newValue, errors.Wrapf(err, "failed to decode value")
+	if node.Type() != ast.NullType {
+		if err := d.decodeValue(ctx, newValue, node); err != nil {
+			return newValue, errors.Wrapf(err, "failed to decode value")
+		}
 	}
 	return newValue, nil
 }


Test patch:
diff --git a/decode_test.go b/decode_test.go
index f0b0c08..0d47a29 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -3027,3 +3027,28 @@ func TestMapKeyCustomUnmarshaler(t *testing.T) {
 		t.Fatalf("expected to have value \"value\", but got %q", val)
 	}
 }
+
+func TestDecoderPreservesDefaultValues(t *testing.T) {
+	type nested struct {
+		Val string `yaml:"val"`
+	}
+
+	type test struct {
+		First   string `yaml:"first"`
+		Default nested `yaml:"nested"`
+	}
+
+	yml := `
+first: "Test"
+nested:
+  # Just some comment here
+#  val: "default"
+`
+	v := test{Default: nested{Val: "default"}}
+	if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
+		t.Fatal(err)
+	}
+	if v.Default.Val != "default" {
+		t.Fatal("decoder doesn't preserve struct defaults")
+	}
+}