1
0
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:
dudaodong
2024-02-20 17:29:32 +08:00
parent c88fd3db86
commit 3a71a8697d
3 changed files with 25 additions and 13 deletions

View File

@@ -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())

View File

@@ -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 {

View File

@@ -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)