From 3f6823ba49a5f82fa0ca7355ce75a94346d057a2 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Mon, 16 Dec 2024 09:26:11 +0800 Subject: [PATCH] fix: handle invalid values in Decoder's decode method --- common/structure/structure.go | 20 ++++++++++++++++++++ common/structure/structure_test.go | 18 ++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/common/structure/structure.go b/common/structure/structure.go index 99c980bc..5bafc178 100644 --- a/common/structure/structure.go +++ b/common/structure/structure.go @@ -86,7 +86,27 @@ func (d *Decoder) Decode(src map[string]any, dst any) error { return nil } +// isNil returns true if the input is nil or a typed nil pointer. +func isNil(input any) bool { + if input == nil { + return true + } + val := reflect.ValueOf(input) + return val.Kind() == reflect.Pointer && val.IsNil() +} + func (d *Decoder) decode(name string, data any, val reflect.Value) error { + if isNil(data) { + // If the data is nil, then we don't set anything + // Maybe we should set to zero value? + return nil + } + if !reflect.ValueOf(data).IsValid() { + // If the input value is invalid, then we just set the value + // to be the zero value. + val.Set(reflect.Zero(val.Type())) + return nil + } for { kind := val.Kind() if kind == reflect.Pointer && val.IsNil() { diff --git a/common/structure/structure_test.go b/common/structure/structure_test.go index e5fe693d..266b828f 100644 --- a/common/structure/structure_test.go +++ b/common/structure/structure_test.go @@ -267,3 +267,21 @@ func TestStructure_TextUnmarshaller(t *testing.T) { err = decoder.Decode(rawMap, s) assert.NotNilf(t, err, "should throw error: %#v", s) } + +func TestStructure_Null(t *testing.T) { + rawMap := map[string]any{ + "opt": map[string]any{ + "bar": nil, + }, + } + + s := struct { + Opt struct { + Bar string `test:"bar,optional"` + } `test:"opt,optional"` + }{} + + err := decoder.Decode(rawMap, &s) + assert.Nil(t, err) + assert.Equal(t, s.Opt.Bar, "") +}