From 38920e3be66ab95e48a4e96023853b6305b52070 Mon Sep 17 00:00:00 2001 From: dudaodong Date: Mon, 29 Jan 2024 11:00:50 +0800 Subject: [PATCH] fix: fix issue #162 --- pointer/pointer.go | 11 +++++++++-- structs/field.go | 14 +++++++++++++- structs/struct.go | 6 ++++++ structs/struct_test.go | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/pointer/pointer.go b/pointer/pointer.go index 91439ed..9b630ef 100644 --- a/pointer/pointer.go +++ b/pointer/pointer.go @@ -4,7 +4,9 @@ // Package pointer contains some util functions to operate go pointer. package pointer -import "reflect" +import ( + "reflect" +) // Of returns a pointer to the value `v`. // Play: https://go.dev/play/p/HFd70x4DrMj @@ -47,5 +49,10 @@ func ExtractPointer(value any) any { if t.Kind() != reflect.Pointer { return value } - return ExtractPointer(v.Elem().Interface()) + + if v.Elem().IsValid() { + return ExtractPointer(v.Elem().Interface()) + } + + return nil } diff --git a/structs/field.go b/structs/field.go index 5815b12..cff2f43 100644 --- a/structs/field.go +++ b/structs/field.go @@ -52,6 +52,16 @@ func (f *Field) IsZero() bool { return reflect.DeepEqual(z, v) } +// IsNil returns true if the given field is nil value. +func (f *Field) IsNil() bool { + v := f.Value() + if v == nil || (reflect.ValueOf(v)).Kind() == reflect.Ptr && reflect.ValueOf(v).IsNil() { + return true + } + + return false +} + // Name returns the name of the given field func (f *Field) Name() string { return f.field.Name @@ -111,7 +121,9 @@ func (f *Field) mapValue(value any) any { ret = v.Interface() } default: - ret = v.Interface() + if v.Kind().String() != "invalid" { + ret = v.Interface() + } } return ret } diff --git a/structs/struct.go b/structs/struct.go index 14207ed..ed73202 100644 --- a/structs/struct.go +++ b/structs/struct.go @@ -71,9 +71,15 @@ func (s *Struct) ToMap() (map[string]any, error) { if !f.IsExported() || f.tag.IsEmpty() || f.tag.Name == "-" { continue } + if f.IsZero() && f.tag.HasOption("omitempty") { continue } + + if f.IsNil() { + continue + } + result[f.tag.Name] = f.mapValue(f.Value()) } diff --git a/structs/struct_test.go b/structs/struct_test.go index 25ffe2c..8040ced 100644 --- a/structs/struct_test.go +++ b/structs/struct_test.go @@ -65,6 +65,45 @@ func TestStruct_ToMap(t *testing.T) { }) } +func Test_ToMap2(t *testing.T) { + t.Parallel() + assert := internal.NewAssert(t, "TestStruct_ToMap") + + type M struct { + Name string `json:"name"` + } + + type S struct { + ID int `json:"id"` + M *M `json:"m"` + } + + s1 := &S{ + ID: 1, + } + var expect1 = map[string]any{"id": 1} + map1, err := ToMap(s1) + + assert.IsNil(err) + assert.Equal(expect1, map1) + + s2 := &S{ + ID: 1, + M: &M{ + Name: "test", + }, + } + var expect2 = map[string]any{ + "id": 1, + "m": map[string]any{ + "name": "test", + }} + map2, err := ToMap(s2) + + assert.IsNil(err) + assert.Equal(expect2, map2) +} + func TestStruct_Fields(t *testing.T) { t.Parallel()