fix issue converting values to custom type pointers (#2585)

This commit is contained in:
John Guo
2023-04-17 16:34:36 +08:00
committed by GitHub
parent fdc027734c
commit 6fb26c44d7
2 changed files with 57 additions and 1 deletions

View File

@ -254,22 +254,50 @@ func doConvert(in doConvertInput) (convertedValue interface{}) {
default:
if in.ReferValue != nil {
var referReflectValue reflect.Value
var (
referReflectValue reflect.Value
)
if v, ok := in.ReferValue.(reflect.Value); ok {
referReflectValue = v
} else {
referReflectValue = reflect.ValueOf(in.ReferValue)
}
defer func() {
if recover() != nil {
in.alreadySetToReferValue = false
if err := bindVarToReflectValue(referReflectValue, in.FromValue, nil); err == nil {
in.alreadySetToReferValue = true
convertedValue = referReflectValue.Interface()
}
}
}()
if referReflectValue.Kind() == reflect.Ptr {
// Type converting for custom type pointers.
// Eg:
// type PayMode int
// type Req struct{
// Mode *PayMode
// }
//
// Struct(`{"Mode": 1000}`, &req)
originType := referReflectValue.Type().Elem()
switch originType.Kind() {
case reflect.Struct:
// Not support some kinds.
default:
in.ToTypeName = originType.Kind().String()
in.ReferValue = nil
refElementValue := reflect.ValueOf(doConvert(in))
originTypeValue := reflect.New(refElementValue.Type()).Elem()
originTypeValue.Set(refElementValue)
in.alreadySetToReferValue = true
return originTypeValue.Addr().Convert(referReflectValue.Type()).Interface()
}
}
in.ToTypeName = referReflectValue.Kind().String()
in.ReferValue = nil
in.alreadySetToReferValue = true
return reflect.ValueOf(doConvert(in)).Convert(referReflectValue.Type()).Interface()
}
return in.FromValue

View File

@ -1321,3 +1321,31 @@ func Test_Scan_WithDoubleSliceAttribute(t *testing.T) {
})
}
func Test_Struct_WithCustomType(t *testing.T) {
type PayMode int
type Req1 struct {
PayMode PayMode
}
type Req2 struct {
PayMode *PayMode
}
var (
params = gconv.Map(`{"PayMode": 1000}`)
req1 *Req1
req2 *Req2
err1 error
err2 error
)
err1 = gconv.Struct(params, &req1)
err2 = gconv.Struct(params, &req2)
gtest.C(t, func(t *gtest.T) {
t.AssertNil(err1)
t.Assert(req1.PayMode, 1000)
t.AssertNil(err2)
t.AssertNE(req2.PayMode, nil)
t.Assert(*req2.PayMode, 1000)
})
}