110 lines
2.9 KiB
Go
110 lines
2.9 KiB
Go
package structx
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
// ValueSetter 值设置器接口
|
|
type ValueSetter interface {
|
|
SetFieldValue(field reflect.Value, value string) (interface{}, error)
|
|
SetSliceElementValue(elemValue reflect.Value, item interface{}, elemType reflect.Type) error
|
|
}
|
|
|
|
// defaultValueSetter 默认值设置器
|
|
type defaultValueSetter struct{}
|
|
|
|
func (ds *defaultValueSetter) SetFieldValue(field reflect.Value, value string) (interface{}, error) {
|
|
fieldType := field.Type()
|
|
|
|
if hasUnmarshalJSON(fieldType) {
|
|
if err := setUnmarshalJSONValue(field, value); err != nil {
|
|
return nil, fmt.Errorf("UnmarshalJSON失败: %w", err)
|
|
}
|
|
return field.Interface(), nil
|
|
}
|
|
|
|
if hasUnmarshalText(fieldType) {
|
|
if err := setUnmarshalTextValue(field, value); err != nil {
|
|
return nil, fmt.Errorf("UnmarshalText失败: %w", err)
|
|
}
|
|
return field.Interface(), nil
|
|
}
|
|
|
|
if fieldType.Kind() == reflect.Ptr {
|
|
return setPointerFieldValue(field, value)
|
|
}
|
|
|
|
if isTypeAlias(fieldType) {
|
|
return setTypeAliasValue(field, value)
|
|
}
|
|
|
|
if isCustomStructType(fieldType) {
|
|
return setCustomTypeValue(field, value)
|
|
}
|
|
|
|
converter, exists := typeConverters[fieldType.Kind()]
|
|
if !exists {
|
|
return nil, fmt.Errorf("不支持的类型: %s", fieldType.Kind())
|
|
}
|
|
|
|
result, err := converter(field, value)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
field.Set(reflect.ValueOf(result))
|
|
return result, nil
|
|
}
|
|
|
|
func (ds *defaultValueSetter) SetSliceElementValue(elemValue reflect.Value, item interface{}, elemType reflect.Type) error {
|
|
if elemType.Kind() == reflect.Ptr {
|
|
if elemValue.IsNil() {
|
|
elemValue.Set(reflect.New(elemType.Elem()))
|
|
}
|
|
return ds.SetSliceElementValue(elemValue.Elem(), item, elemType.Elem())
|
|
}
|
|
|
|
if hasUnmarshalJSON(elemType) {
|
|
return setUnmarshalJSONValue(elemValue, item)
|
|
}
|
|
|
|
switch elemType.Kind() {
|
|
case reflect.String:
|
|
elemValue.SetString(convertToString(item))
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
num, err := convertToFloat64(item)
|
|
if err != nil {
|
|
return fmt.Errorf("无法转换为整型: %w", err)
|
|
}
|
|
elemValue.SetInt(int64(num))
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
num, err := convertToFloat64(item)
|
|
if err != nil {
|
|
return fmt.Errorf("无法转换为无符号整型: %w", err)
|
|
}
|
|
elemValue.SetUint(uint64(num))
|
|
case reflect.Float32, reflect.Float64:
|
|
num, err := convertToFloat64(item)
|
|
if err != nil {
|
|
return fmt.Errorf("无法转换为浮点型: %w", err)
|
|
}
|
|
elemValue.SetFloat(num)
|
|
case reflect.Bool:
|
|
if b, ok := item.(bool); ok {
|
|
elemValue.SetBool(b)
|
|
} else {
|
|
return fmt.Errorf("无法转换为布尔型")
|
|
}
|
|
case reflect.Struct:
|
|
if isBasicStructType(elemType) {
|
|
return setBasicStructElement(elemValue, item)
|
|
}
|
|
return setStructElement(elemValue, item)
|
|
default:
|
|
return fmt.Errorf("不支持的切片元素类型: %s", elemType.Kind())
|
|
}
|
|
|
|
return nil
|
|
}
|