Skip to content

Commit

Permalink
Merge pull request #83 from k1LoW/nil-ptr-value-and-empty-ptr-value
Browse files Browse the repository at this point in the history
Distinguish between empty ptr value (e.g. *int, *string) and nil ptr value
  • Loading branch information
goccy authored Feb 22, 2020
2 parents 90ec442 + 0b3ce01 commit e260838
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 0 deletions.
3 changes: 3 additions & 0 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,9 @@ func (d *Decoder) createDecodedNewValue(typ reflect.Type, node ast.Node) (reflec
return newValue, nil
}
}
if node.Type() == ast.NullType {
return reflect.Zero(typ), nil
}
newValue := d.createDecodableValue(typ)
if err := d.decodeValue(newValue, node); err != nil {
return newValue, errors.Wrapf(err, "failed to decode value")
Expand Down
56 changes: 56 additions & 0 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,34 @@ func TestUnmarshalableString(t *testing.T) {
})
}

type unmarshalablePtrStringContainer struct {
V *string `yaml:"value" json:"value"`
}

func TestUnmarshalablePtrString(t *testing.T) {
t.Run("empty string", func(t *testing.T) {
t.Parallel()
var container unmarshalablePtrStringContainer
if err := yaml.Unmarshal([]byte(`value: ""`), &container); err != nil {
t.Fatalf("failed to unmarshal %v", err)
}
if *container.V != "" {
t.Fatalf("expected empty string, but %q is set", *container.V)
}
})

t.Run("null", func(t *testing.T) {
t.Parallel()
var container unmarshalablePtrStringContainer
if err := yaml.Unmarshal([]byte(`value: null`), &container); err != nil {
t.Fatalf("failed to unmarshal %v", err)
}
if container.V != (*string)(nil) {
t.Fatalf("expected nil, but %q is set", *container.V)
}
})
}

type unmarshalableIntValue int

func (v *unmarshalableIntValue) UnmarshalYAML(raw []byte) error {
Expand Down Expand Up @@ -1448,3 +1476,31 @@ func TestUnmarshalableInt(t *testing.T) {
}
})
}

type unmarshalablePtrIntContainer struct {
V *int `yaml:"value" json:"value"`
}

func TestUnmarshalablePtrInt(t *testing.T) {
t.Run("empty int", func(t *testing.T) {
t.Parallel()
var container unmarshalablePtrIntContainer
if err := yaml.Unmarshal([]byte(`value: 0`), &container); err != nil {
t.Fatalf("failed to unmarshal %v", err)
}
if *container.V != 0 {
t.Fatalf("expected 0, but %q is set", *container.V)
}
})

t.Run("null", func(t *testing.T) {
t.Parallel()
var container unmarshalablePtrIntContainer
if err := yaml.Unmarshal([]byte(`value: null`), &container); err != nil {
t.Fatalf("failed to unmarshal %v", err)
}
if container.V != (*int)(nil) {
t.Fatalf("expected nil, but %q is set", *container.V)
}
})
}
43 changes: 43 additions & 0 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (
"github.com/goccy/go-yaml/ast"
)

var zero = 0
var emptyStr = ""

func TestEncoder(t *testing.T) {
tests := []struct {
source string
Expand Down Expand Up @@ -249,6 +252,46 @@ func TestEncoder(t *testing.T) {
1, 0,
},
},
{
"a: \"\"\n",
struct {
A string
}{
"",
},
},
{
"a: null\n",
struct {
A *string
}{
nil,
},
},
{
"a: \"\"\n",
struct {
A *string
}{
&emptyStr,
},
},
{
"a: null\n",
struct {
A *int
}{
nil,
},
},
{
"a: 0\n",
struct {
A *int
}{
&zero,
},
},

// Conditional flag
{
Expand Down

0 comments on commit e260838

Please sign in to comment.