mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 12:52:28 +08:00
fix: fix issue #169
This commit is contained in:
@@ -307,8 +307,7 @@ func HasKey[K comparable, V any](m map[K]V, key K) bool {
|
|||||||
|
|
||||||
// MapToStruct converts map to struct
|
// MapToStruct converts map to struct
|
||||||
// Play: todo
|
// Play: todo
|
||||||
func MapToStruct(m map[string]interface{}, structObj interface{}) error {
|
func MapToStruct(m map[string]any, structObj any) error {
|
||||||
|
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
err := setStructField(structObj, k, v)
|
err := setStructField(structObj, k, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -341,7 +340,12 @@ func setStructField(structObj any, fieldName string, fieldValue any) error {
|
|||||||
|
|
||||||
if fieldVal.Type() != val.Type() {
|
if fieldVal.Type() != val.Type() {
|
||||||
|
|
||||||
if m, ok := fieldValue.(map[string]interface{}); ok {
|
if val.CanConvert(fieldVal.Type()) {
|
||||||
|
fieldVal.Set(val.Convert(fieldVal.Type()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if m, ok := fieldValue.(map[string]any); ok {
|
||||||
|
|
||||||
if fieldVal.Kind() == reflect.Struct {
|
if fieldVal.Kind() == reflect.Struct {
|
||||||
return MapToStruct(m, fieldVal.Addr().Interface())
|
return MapToStruct(m, fieldVal.Addr().Interface())
|
||||||
|
|||||||
@@ -62,18 +62,25 @@ var _ = func() struct{} {
|
|||||||
*/
|
*/
|
||||||
// Play: https://go.dev/play/p/4K7KBEPgS5M
|
// Play: https://go.dev/play/p/4K7KBEPgS5M
|
||||||
func MapTo(src any, dst any) error {
|
func MapTo(src any, dst any) error {
|
||||||
|
|
||||||
dstRef := reflect.ValueOf(dst)
|
dstRef := reflect.ValueOf(dst)
|
||||||
|
|
||||||
if dstRef.Kind() != reflect.Ptr {
|
if dstRef.Kind() != reflect.Ptr {
|
||||||
return fmt.Errorf("dst is not ptr")
|
return fmt.Errorf("dst is not ptr")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dstElem := dstRef.Type().Elem()
|
||||||
|
if dstElem.Kind() == reflect.Struct {
|
||||||
|
srcMap := src.(map[string]interface{})
|
||||||
|
return MapToStruct(srcMap, dst)
|
||||||
|
}
|
||||||
|
|
||||||
dstRef = reflect.Indirect(dstRef)
|
dstRef = reflect.Indirect(dstRef)
|
||||||
|
|
||||||
srcRef := reflect.ValueOf(src)
|
srcRef := reflect.ValueOf(src)
|
||||||
if srcRef.Kind() == reflect.Ptr || srcRef.Kind() == reflect.Interface {
|
if srcRef.Kind() == reflect.Ptr || srcRef.Kind() == reflect.Interface {
|
||||||
srcRef = srcRef.Elem()
|
srcRef = srcRef.Elem()
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, ok := mapHandlers[srcRef.Kind()]; ok {
|
if f, ok := mapHandlers[srcRef.Kind()]; ok {
|
||||||
return f(srcRef, dstRef)
|
return f(srcRef, dstRef)
|
||||||
}
|
}
|
||||||
@@ -121,10 +128,7 @@ func convertSlice(src reflect.Value, dst reflect.Value) error {
|
|||||||
|
|
||||||
func convertMap(src reflect.Value, dst reflect.Value) error {
|
func convertMap(src reflect.Value, dst reflect.Value) error {
|
||||||
if src.Kind() != reflect.Map || dst.Kind() != reflect.Struct {
|
if src.Kind() != reflect.Map || dst.Kind() != reflect.Struct {
|
||||||
// if src.Kind() == reflect.Map {
|
if src.Kind() == reflect.Interface && dst.IsValid() {
|
||||||
// return convertMap(src, dst)
|
|
||||||
// } else
|
|
||||||
if src.Kind() == reflect.Interface {
|
|
||||||
return convertMap(src.Elem(), dst)
|
return convertMap(src.Elem(), dst)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("src or dst type error,%s,%s", src.Type().String(), dst.Type().String())
|
return fmt.Errorf("src or dst type error,%s,%s", src.Type().String(), dst.Type().String())
|
||||||
@@ -132,7 +136,9 @@ func convertMap(src reflect.Value, dst reflect.Value) error {
|
|||||||
}
|
}
|
||||||
dstType := dst.Type()
|
dstType := dst.Type()
|
||||||
num := dstType.NumField()
|
num := dstType.NumField()
|
||||||
|
|
||||||
exist := map[string]int{}
|
exist := map[string]int{}
|
||||||
|
|
||||||
for i := 0; i < num; i++ {
|
for i := 0; i < num; i++ {
|
||||||
k := dstType.Field(i).Tag.Get("json")
|
k := dstType.Field(i).Tag.Get("json")
|
||||||
if k == "" {
|
if k == "" {
|
||||||
@@ -141,7 +147,6 @@ func convertMap(src reflect.Value, dst reflect.Value) error {
|
|||||||
if strings.Contains(k, ",") {
|
if strings.Contains(k, ",") {
|
||||||
taglist := strings.Split(k, ",")
|
taglist := strings.Split(k, ",")
|
||||||
if taglist[0] == "" {
|
if taglist[0] == "" {
|
||||||
|
|
||||||
k = dstType.Field(i).Name
|
k = dstType.Field(i).Name
|
||||||
} else {
|
} else {
|
||||||
k = taglist[0]
|
k = taglist[0]
|
||||||
@@ -153,9 +158,11 @@ func convertMap(src reflect.Value, dst reflect.Value) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
keys := src.MapKeys()
|
keys := src.MapKeys()
|
||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if index, ok := exist[key.String()]; ok {
|
if index, ok := exist[key.String()]; ok {
|
||||||
v := dst.Field(index)
|
v := dst.Field(index)
|
||||||
|
|
||||||
if v.Kind() == reflect.Struct {
|
if v.Kind() == reflect.Struct {
|
||||||
err := convertMap(src.MapIndex(key), v)
|
err := convertMap(src.MapIndex(key), v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
Person struct {
|
Person struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Age int `json:"age"`
|
Age int `json:"age"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
Address Address `json:"address"`
|
Address *Address `json:"address"`
|
||||||
}
|
}
|
||||||
|
|
||||||
Address struct {
|
Address struct {
|
||||||
@@ -38,6 +38,7 @@ func TestStructType(t *testing.T) {
|
|||||||
var p Person
|
var p Person
|
||||||
err := MapTo(src, &p)
|
err := MapTo(src, &p)
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
|
|
||||||
assert.Equal(src["name"], p.Name)
|
assert.Equal(src["name"], p.Name)
|
||||||
assert.Equal(src["age"], p.Age)
|
assert.Equal(src["age"], p.Age)
|
||||||
assert.Equal(src["phone"], p.Phone)
|
assert.Equal(src["phone"], p.Phone)
|
||||||
|
|||||||
Reference in New Issue
Block a user