mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
@ -534,14 +534,20 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, ma
|
||||
structFieldValue.Set(reflectArray)
|
||||
|
||||
case reflect.Ptr:
|
||||
item := reflect.New(structFieldValue.Type().Elem())
|
||||
if err, ok = bindVarToReflectValueWithInterfaceCheck(item, value); ok {
|
||||
structFieldValue.Set(item)
|
||||
return err
|
||||
}
|
||||
elem := item.Elem()
|
||||
if err = bindVarToReflectValue(elem, value, mapping); err == nil {
|
||||
structFieldValue.Set(elem.Addr())
|
||||
if structFieldValue.IsNil() || structFieldValue.IsZero() {
|
||||
// Nil or empty pointer, it creates a new one.
|
||||
item := reflect.New(structFieldValue.Type().Elem())
|
||||
if err, ok = bindVarToReflectValueWithInterfaceCheck(item, value); ok {
|
||||
structFieldValue.Set(item)
|
||||
return err
|
||||
}
|
||||
elem := item.Elem()
|
||||
if err = bindVarToReflectValue(elem, value, mapping); err == nil {
|
||||
structFieldValue.Set(elem.Addr())
|
||||
}
|
||||
} else {
|
||||
// Not empty pointer, it assigns values to it.
|
||||
return bindVarToReflectValue(structFieldValue.Elem(), value, mapping)
|
||||
}
|
||||
|
||||
// It mainly and specially handles the interface of nil value.
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gtype"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
@ -1480,3 +1481,76 @@ func Test_Struct_Time_All(t *testing.T) {
|
||||
t.Assert(user.CreateTime.Time.UTC().String(), now.UTC().String())
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Issue1946(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type B struct {
|
||||
init *gtype.Bool
|
||||
Name string
|
||||
}
|
||||
type A struct {
|
||||
B *B
|
||||
}
|
||||
a := &A{
|
||||
B: &B{
|
||||
init: gtype.NewBool(true),
|
||||
},
|
||||
}
|
||||
err := gconv.Struct(g.Map{
|
||||
"B": g.Map{
|
||||
"Name": "init",
|
||||
},
|
||||
}, a)
|
||||
t.AssertNil(err)
|
||||
t.Assert(a.B.Name, "init")
|
||||
t.Assert(a.B.init.Val(), true)
|
||||
})
|
||||
// It cannot change private attribute.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type B struct {
|
||||
init *gtype.Bool
|
||||
Name string
|
||||
}
|
||||
type A struct {
|
||||
B *B
|
||||
}
|
||||
a := &A{
|
||||
B: &B{
|
||||
init: gtype.NewBool(true),
|
||||
},
|
||||
}
|
||||
err := gconv.Struct(g.Map{
|
||||
"B": g.Map{
|
||||
"init": 0,
|
||||
"Name": "init",
|
||||
},
|
||||
}, a)
|
||||
t.AssertNil(err)
|
||||
t.Assert(a.B.Name, "init")
|
||||
t.Assert(a.B.init.Val(), true)
|
||||
})
|
||||
// It can change public attribute.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
type B struct {
|
||||
Init *gtype.Bool
|
||||
Name string
|
||||
}
|
||||
type A struct {
|
||||
B *B
|
||||
}
|
||||
a := &A{
|
||||
B: &B{
|
||||
Init: gtype.NewBool(),
|
||||
},
|
||||
}
|
||||
err := gconv.Struct(g.Map{
|
||||
"B": g.Map{
|
||||
"Init": 1,
|
||||
"Name": "init",
|
||||
},
|
||||
}, a)
|
||||
t.AssertNil(err)
|
||||
t.Assert(a.B.Name, "init")
|
||||
t.Assert(a.B.Init.Val(), true)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user