mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
fix issue converting values to custom type pointers (#2585)
This commit is contained in:
@ -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
|
||||
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user