191 lines
4.7 KiB
Go
191 lines
4.7 KiB
Go
package structx
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
// 工具函数
|
|
|
|
func getJSONTagName(field reflect.StructField) string {
|
|
jsonTag := field.Tag.Get("json")
|
|
if jsonTag == "" || jsonTag == "-" {
|
|
return field.Name
|
|
}
|
|
return strings.Split(jsonTag, ",")[0]
|
|
}
|
|
|
|
// 是否实现了json.Unmarshaler接口
|
|
func hasUnmarshalJSON(t reflect.Type) bool {
|
|
if t.Kind() == reflect.Ptr {
|
|
t = t.Elem()
|
|
}
|
|
unmarshalerType := reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
|
|
return t.Implements(unmarshalerType) || reflect.PointerTo(t).Implements(unmarshalerType)
|
|
}
|
|
|
|
// 是否实现了text.Unmarshaler接口
|
|
func hasUnmarshalText(t reflect.Type) bool {
|
|
if t.Kind() == reflect.Ptr {
|
|
t = t.Elem()
|
|
}
|
|
textUnmarshalerType := reflect.TypeOf((*interface {
|
|
UnmarshalText([]byte) error
|
|
})(nil)).Elem()
|
|
return t.Implements(textUnmarshalerType) || reflect.PointerTo(t).Implements(textUnmarshalerType)
|
|
}
|
|
|
|
// 设置json.Unmarshaler接口的值
|
|
func setUnmarshalJSONValue(field reflect.Value, value interface{}) error {
|
|
jsonBytes, err := json.Marshal(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var fieldAddr reflect.Value
|
|
if field.CanAddr() {
|
|
fieldAddr = field.Addr()
|
|
} else {
|
|
temp := reflect.New(field.Type())
|
|
temp.Elem().Set(field)
|
|
fieldAddr = temp
|
|
}
|
|
|
|
if unmarshaler, ok := fieldAddr.Interface().(json.Unmarshaler); ok {
|
|
return unmarshaler.UnmarshalJSON(jsonBytes)
|
|
}
|
|
return fmt.Errorf("类型未实现Unmarshaler")
|
|
}
|
|
|
|
// 设置text.Unmarshaler接口的值
|
|
func setUnmarshalTextValue(field reflect.Value, value string) error {
|
|
var fieldAddr reflect.Value
|
|
if field.CanAddr() {
|
|
fieldAddr = field.Addr()
|
|
} else {
|
|
temp := reflect.New(field.Type())
|
|
temp.Elem().Set(field)
|
|
fieldAddr = temp
|
|
}
|
|
|
|
if unmarshaler, ok := fieldAddr.Interface().(interface {
|
|
UnmarshalText([]byte) error
|
|
}); ok {
|
|
return unmarshaler.UnmarshalText([]byte(value))
|
|
}
|
|
return fmt.Errorf("类型未实现UnmarshalText")
|
|
}
|
|
|
|
// 是否是基础结构体类型
|
|
func isBasicStructType(t reflect.Type) bool {
|
|
if t.Kind() == reflect.Ptr {
|
|
t = t.Elem()
|
|
}
|
|
return basicStructTypes[t.String()]
|
|
}
|
|
|
|
// 设置基础结构体类型的值
|
|
func setBasicStructValue(field reflect.Value, value string) error {
|
|
if hasUnmarshalText(field.Type()) {
|
|
return setUnmarshalTextValue(field, value)
|
|
}
|
|
return json.Unmarshal([]byte(value), field.Addr().Interface())
|
|
}
|
|
|
|
// 设置指针类型的值
|
|
func setPointerFieldValue(field reflect.Value, value string) (interface{}, error) {
|
|
if field.Kind() != reflect.Ptr {
|
|
return nil, fmt.Errorf("期望指针类型")
|
|
}
|
|
if field.IsNil() {
|
|
field.Set(reflect.New(field.Type().Elem()))
|
|
}
|
|
|
|
return new(defaultValueSetter).SetFieldValue(field.Elem(), value)
|
|
}
|
|
|
|
// 是否是类型别名
|
|
func isTypeAlias(t reflect.Type) bool {
|
|
if t.Kind() == reflect.Ptr {
|
|
t = t.Elem()
|
|
}
|
|
return t.PkgPath() != "" && basicKinds[t.Kind()]
|
|
}
|
|
|
|
// 设置类型别名的值
|
|
func setTypeAliasValue(field reflect.Value, value string) (interface{}, error) {
|
|
baseType := getBaseTypeFromAlias(field.Type())
|
|
if baseType == nil {
|
|
return nil, fmt.Errorf("无法获取基础类型")
|
|
}
|
|
|
|
converter, exists := typeConverters[baseType.Kind()]
|
|
if !exists {
|
|
return nil, fmt.Errorf("不支持的基础类型")
|
|
}
|
|
|
|
baseValue := reflect.New(baseType).Elem()
|
|
result, err := converter(baseValue, value)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
convertedValue, err := convertToTypeAlias(field.Type(), result)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
field.Set(reflect.ValueOf(convertedValue))
|
|
return convertedValue, nil
|
|
}
|
|
|
|
// 是否是自定义结构体类型
|
|
func isCustomStructType(t reflect.Type) bool {
|
|
if t.Kind() == reflect.Ptr {
|
|
t = t.Elem()
|
|
}
|
|
return t.PkgPath() != "" && !isBasicStructType(t) && !isTypeAlias(t) && t.Kind() == reflect.Struct
|
|
}
|
|
|
|
// 设置自定义结构体类型的值
|
|
func setCustomTypeValue(field reflect.Value, value string) (interface{}, error) {
|
|
if hasUnmarshalText(field.Type()) {
|
|
if err := setUnmarshalTextValue(field, value); err != nil {
|
|
return nil, err
|
|
}
|
|
return field.Interface(), nil
|
|
}
|
|
|
|
var jsonData interface{}
|
|
if err := json.Unmarshal([]byte(value), &jsonData); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
jsonBytes, err := json.Marshal(jsonData)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := json.Unmarshal(jsonBytes, field.Addr().Interface()); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return field.Interface(), nil
|
|
}
|
|
|
|
// 设置基础结构体元素的值
|
|
func setBasicStructElement(elemValue reflect.Value, item interface{}) error {
|
|
return setStructElement(elemValue, item)
|
|
}
|
|
|
|
// 设置结构体元素的值
|
|
func setStructElement(elemValue reflect.Value, item interface{}) error {
|
|
jsonBytes, err := json.Marshal(item)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return json.Unmarshal(jsonBytes, elemValue.Addr().Interface())
|
|
}
|