mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
improve package gconv for detailed handling of interface attributes
This commit is contained in:
@ -7,7 +7,6 @@
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/json"
|
||||
"reflect"
|
||||
@ -325,7 +324,7 @@ func doMapToMap(params interface{}, pointer interface{}, deep bool, mapping ...m
|
||||
paramsKind = paramsRv.Kind()
|
||||
}
|
||||
if paramsKind != reflect.Map {
|
||||
return errors.New("params should be type of map")
|
||||
return gerror.New("params should be type of map")
|
||||
}
|
||||
// Empty params map, no need continue.
|
||||
if paramsRv.Len() == 0 {
|
||||
@ -343,7 +342,7 @@ func doMapToMap(params interface{}, pointer interface{}, deep bool, mapping ...m
|
||||
pointerKind = pointerRv.Kind()
|
||||
}
|
||||
if pointerKind != reflect.Map {
|
||||
return errors.New("pointer should be type of *map")
|
||||
return gerror.New("pointer should be type of *map")
|
||||
}
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
@ -434,7 +433,7 @@ func doMapToMaps(params interface{}, pointer interface{}, deep bool, mapping ...
|
||||
paramsKind = paramsRv.Kind()
|
||||
}
|
||||
if paramsKind != reflect.Map {
|
||||
return errors.New("params should be type of map")
|
||||
return gerror.New("params should be type of map")
|
||||
}
|
||||
// Empty params map, no need continue.
|
||||
if paramsRv.Len() == 0 {
|
||||
@ -449,7 +448,7 @@ func doMapToMaps(params interface{}, pointer interface{}, deep bool, mapping ...
|
||||
pointerKind = pointerRv.Kind()
|
||||
}
|
||||
if pointerKind != reflect.Map {
|
||||
return errors.New("pointer should be type of *map/**map")
|
||||
return gerror.New("pointer should be type of *map/**map")
|
||||
}
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
@ -19,7 +19,7 @@ func Scan(params interface{}, pointer interface{}, mapping ...map[string]string)
|
||||
t := reflect.TypeOf(pointer)
|
||||
k := t.Kind()
|
||||
if k != reflect.Ptr {
|
||||
return fmt.Errorf("params should be type of pointer, but got: %v", k)
|
||||
return gerror.Newf("params should be type of pointer, but got: %v", k)
|
||||
}
|
||||
switch t.Elem().Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
@ -37,7 +37,7 @@ func ScanDeep(params interface{}, pointer interface{}, mapping ...map[string]str
|
||||
t := reflect.TypeOf(pointer)
|
||||
k := t.Kind()
|
||||
if k != reflect.Ptr {
|
||||
return fmt.Errorf("params should be type of pointer, but got: %v", k)
|
||||
return gerror.Newf("params should be type of pointer, but got: %v", k)
|
||||
}
|
||||
switch t.Elem().Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
|
||||
@ -7,7 +7,6 @@
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"github.com/gogf/gf/internal/empty"
|
||||
@ -50,10 +49,10 @@ func StructDeep(params interface{}, pointer interface{}, mapping ...map[string]s
|
||||
// doStruct is the core internal converting function for any data to struct recursively or not.
|
||||
func doStruct(params interface{}, pointer interface{}, recursive bool, mapping ...map[string]string) (err error) {
|
||||
if params == nil {
|
||||
return errors.New("params cannot be nil")
|
||||
return gerror.New("params cannot be nil")
|
||||
}
|
||||
if pointer == nil {
|
||||
return errors.New("object pointer cannot be nil")
|
||||
return gerror.New("object pointer cannot be nil")
|
||||
}
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
@ -65,7 +64,7 @@ func doStruct(params interface{}, pointer interface{}, recursive bool, mapping .
|
||||
// paramsMap is the map[string]interface{} type variable for params.
|
||||
paramsMap := MapDeep(params)
|
||||
if paramsMap == nil {
|
||||
return fmt.Errorf("invalid params: %v", params)
|
||||
return gerror.Newf("invalid params: %v", params)
|
||||
}
|
||||
|
||||
// UnmarshalValue.
|
||||
@ -81,15 +80,23 @@ func doStruct(params interface{}, pointer interface{}, recursive bool, mapping .
|
||||
if !ok {
|
||||
rv := reflect.ValueOf(pointer)
|
||||
if kind := rv.Kind(); kind != reflect.Ptr {
|
||||
return fmt.Errorf("object pointer should be type of '*struct', but got '%v'", kind)
|
||||
return gerror.Newf("object pointer should be type of '*struct', but got '%v'", kind)
|
||||
}
|
||||
// Using IsNil on reflect.Ptr variable is OK.
|
||||
if !rv.IsValid() || rv.IsNil() {
|
||||
return errors.New("object pointer cannot be nil")
|
||||
return gerror.New("object pointer cannot be nil")
|
||||
}
|
||||
elem = rv.Elem()
|
||||
}
|
||||
|
||||
// Check if an invalid interface.
|
||||
if elem.Kind() == reflect.Interface {
|
||||
elem = elem.Elem()
|
||||
if !elem.IsValid() {
|
||||
return gerror.New("interface type converting is not supported")
|
||||
}
|
||||
}
|
||||
|
||||
// It automatically creates struct object if necessary.
|
||||
// For example, if <pointer> is **User, then <elem> is *User, which is a pointer to User.
|
||||
if elem.Kind() == reflect.Ptr {
|
||||
@ -360,7 +367,7 @@ func bindVarToReflectValue(structFieldValue reflect.Value, value interface{}, re
|
||||
default:
|
||||
defer func() {
|
||||
if e := recover(); e != nil {
|
||||
err = errors.New(
|
||||
err = gerror.New(
|
||||
fmt.Sprintf(`cannot convert value "%+v" to type "%s"`,
|
||||
value,
|
||||
structFieldValue.Type().String(),
|
||||
|
||||
@ -7,8 +7,6 @@
|
||||
package gconv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/errors/gerror"
|
||||
"reflect"
|
||||
)
|
||||
@ -32,10 +30,10 @@ func StructsDeep(params interface{}, pointer interface{}, mapping ...map[string]
|
||||
// it will create the struct/pointer internally.
|
||||
func doStructs(params interface{}, pointer interface{}, deep bool, mapping ...map[string]string) (err error) {
|
||||
if params == nil {
|
||||
return errors.New("params cannot be nil")
|
||||
return gerror.New("params cannot be nil")
|
||||
}
|
||||
if pointer == nil {
|
||||
return errors.New("object pointer cannot be nil")
|
||||
return gerror.New("object pointer cannot be nil")
|
||||
}
|
||||
defer func() {
|
||||
// Catch the panic, especially the reflect operation panics.
|
||||
@ -47,7 +45,7 @@ func doStructs(params interface{}, pointer interface{}, deep bool, mapping ...ma
|
||||
if !ok {
|
||||
pointerRv = reflect.ValueOf(pointer)
|
||||
if kind := pointerRv.Kind(); kind != reflect.Ptr {
|
||||
return fmt.Errorf("pointer should be type of pointer, but got: %v", kind)
|
||||
return gerror.Newf("pointer should be type of pointer, but got: %v", kind)
|
||||
}
|
||||
}
|
||||
params = Maps(params)
|
||||
@ -101,6 +99,6 @@ func doStructs(params interface{}, pointer interface{}, deep bool, mapping ...ma
|
||||
pointerRv.Elem().Set(array)
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("params should be type of slice, but got: %v", reflectKind)
|
||||
return gerror.Newf("params should be type of slice, but got: %v", reflectKind)
|
||||
}
|
||||
}
|
||||
|
||||
@ -910,3 +910,53 @@ func Test_Struct_UnmarshalValue(t *testing.T) {
|
||||
t.AssertNE(err, nil)
|
||||
})
|
||||
}
|
||||
|
||||
type T struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (t *T) Test() string {
|
||||
return t.Name
|
||||
}
|
||||
|
||||
type TestInterface interface {
|
||||
Test() string
|
||||
}
|
||||
|
||||
type TestStruct struct {
|
||||
TestInterface
|
||||
}
|
||||
|
||||
func Test_Struct_WithInterfaceAttr(t *testing.T) {
|
||||
// Implemented interface attribute.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
v1 := TestStruct{
|
||||
TestInterface: &T{"john"},
|
||||
}
|
||||
v2 := g.Map{}
|
||||
err := gconv.StructDeep(v2, &v1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(v1.Test(), "john")
|
||||
})
|
||||
// Implemented interface attribute.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
v1 := TestStruct{
|
||||
TestInterface: &T{"john"},
|
||||
}
|
||||
v2 := g.Map{
|
||||
"name": "test",
|
||||
}
|
||||
err := gconv.StructDeep(v2, &v1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(v1.Test(), "test")
|
||||
})
|
||||
// No implemented interface attribute.
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
v1 := TestStruct{}
|
||||
v2 := g.Map{
|
||||
"name": "test",
|
||||
}
|
||||
err := gconv.StructDeep(v2, &v1)
|
||||
t.AssertNE(err, nil)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user