mirror of
https://github.com/jefferyjob/go-easy-utils.git
synced 2025-09-27 03:15:55 +08:00
104 lines
2.7 KiB
Go
104 lines
2.7 KiB
Go
package jsonx
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
func parseMap(value reflect.Value, data map[string]any) error {
|
|
if value.Kind() != reflect.Map {
|
|
return ErrNotMap
|
|
}
|
|
|
|
valueType := value.Type().Elem()
|
|
newMap := reflect.MakeMapWithSize(value.Type(), len(data))
|
|
|
|
for key, val := range data {
|
|
newKey := reflect.ValueOf(key)
|
|
|
|
if valueType.Kind() == reflect.Interface {
|
|
newMap.SetMapIndex(newKey, reflect.ValueOf(val))
|
|
} else if valueType.Kind() == reflect.Map {
|
|
newElem := reflect.New(valueType).Elem()
|
|
if err := parseMap(newElem, val.(map[string]any)); err != nil {
|
|
return err
|
|
}
|
|
newMap.SetMapIndex(newKey, newElem)
|
|
} else {
|
|
newVal := reflect.New(valueType).Elem()
|
|
if err := parseValue(newVal, val); err != nil {
|
|
return err
|
|
}
|
|
newMap.SetMapIndex(newKey, newVal)
|
|
}
|
|
}
|
|
|
|
value.Set(newMap)
|
|
return nil
|
|
}
|
|
|
|
func parseValue(fieldVal reflect.Value, item any) error {
|
|
switch fieldVal.Kind() {
|
|
case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
|
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
|
reflect.Float32, reflect.Float64, reflect.Bool:
|
|
if err := parsePrimitiveValue(fieldVal, item); err != nil {
|
|
return err
|
|
}
|
|
case reflect.Struct:
|
|
if subData, ok := item.(map[string]any); ok {
|
|
if err := ToStruct(convertToJSONString(subData), fieldVal.Addr().Interface()); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
return fmt.Errorf("unexpected value type for struct: %T", item)
|
|
}
|
|
case reflect.Slice:
|
|
if arr, ok := item.([]any); ok {
|
|
elemType := fieldVal.Type().Elem()
|
|
sliceVal := reflect.MakeSlice(fieldVal.Type(), len(arr), len(arr))
|
|
for i, elem := range arr {
|
|
elemVal := reflect.New(elemType).Elem()
|
|
if err := parseValue(elemVal, elem); err != nil {
|
|
return err
|
|
}
|
|
sliceVal.Index(i).Set(elemVal)
|
|
}
|
|
fieldVal.Set(sliceVal)
|
|
} else {
|
|
return fmt.Errorf("unexpected value type for slice: %T", item)
|
|
}
|
|
case reflect.Map:
|
|
if mapData, ok := item.(map[string]any); ok {
|
|
mapType := fieldVal.Type()
|
|
if fieldVal.IsNil() {
|
|
fieldVal.Set(reflect.MakeMap(mapType))
|
|
}
|
|
elemType := mapType.Elem()
|
|
mapVal := fieldVal
|
|
for k, v := range mapData {
|
|
keyVal := reflect.New(mapType.Key()).Elem()
|
|
if err := parseValue(keyVal, k); err != nil {
|
|
return err
|
|
}
|
|
elemVal := reflect.New(elemType).Elem()
|
|
if err := parseValue(elemVal, v); err != nil {
|
|
return err
|
|
}
|
|
mapVal.SetMapIndex(keyVal, elemVal)
|
|
}
|
|
} else {
|
|
return fmt.Errorf("unexpected value type for map: %T", item)
|
|
}
|
|
case reflect.Interface:
|
|
if item == nil {
|
|
fieldVal.Set(reflect.Zero(fieldVal.Type()))
|
|
} else {
|
|
fieldVal.Set(reflect.ValueOf(item))
|
|
}
|
|
default:
|
|
return fmt.Errorf("unsupported kind: %s", fieldVal.Kind())
|
|
}
|
|
return nil
|
|
}
|