reflux/rfx.go
what 72d670be0b feat: 增强 map 大小写不敏感支持和函数重命名
- 新增 tryMapFieldKey 函数,返回 map 中实际存在的键(支持大小写转换)
- 优化 setFieldValue 方法,使用 tryMapFieldKey 查找已存在字段并更新
- 优化 setNestedValue 方法,修复嵌套 map 大小写处理和 interface 包装问题
- 重命名函数以提高代码清晰度:
  - tryStructField → tryStructFieldValue
  - tryMapField → tryMapFieldValue
  - tryMapFieldWithKey → tryMapFieldKey
- 新增 rfx_map_case_test.go 包含 16 个测试用例,覆盖基本、嵌套、边界等场景
2025-12-09 16:55:13 +08:00

979 lines
23 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package reflux
import (
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"
"git.fsdpf.net/go/reflux/valuex"
"github.com/spf13/cast"
)
// rfx 是 R 接口的具体实现
// 通过封装 reflect.Value 提供了对结构体、切片、映射等类型的统一访问方式
type rfx struct {
// value 存储底层的反射值
// 该值应该是指针类型,以支持修改操作
value reflect.Value
}
// Get 通过路径获取嵌套字段的值
func (r *rfx) Get(p ...string) R {
return &rfx{value: getValueByPath(r.value, p...)}
}
// Scope 创建一个指定路径的作用域视图(深度克隆)
func (r *rfx) Scope(p ...string) R {
v := getValueByPath(r.value, p...)
if !v.IsValid() {
return &rfx{value: reflect.Value{}}
}
// 深度克隆值
cloned := DeepClone(v)
return &rfx{value: cloned}
}
// Set 设置指定路径的值,支持链式调用
// 如果路径不存在或设置失败,会 panic
func (r *rfx) Set(key string, v any) R {
// 展开路径
keys := expandPath(key)
if len(keys) == 0 {
panic("rfx: empty path")
}
// 如果只有一个键,直接设置
if len(keys) == 1 {
target := r.getParentValue()
if !target.IsValid() {
panic(fmt.Sprintf("rfx: invalid value for path '%s'", key))
}
if !target.CanSet() {
panic(fmt.Sprintf("rfx: cannot set value at path '%s'", key))
}
if !r.setFieldValue(target, keys[0], v) {
panic(fmt.Sprintf("rfx: failed to set value at path '%s'", key))
}
return r
}
// 多个键的情况,需要特殊处理 map 中的 struct
if !r.setNestedValue(r.value, keys, v) {
panic(fmt.Sprintf("rfx: failed to set value at path '%s'", key))
}
return r
}
// Append 追加指定路径的值
// 参数 items 为要追加的值
// 返回当前 R 实例以支持链式调用
func (r *rfx) Append(items ...any) R {
// 没有要追加的元素,直接返回
if len(items) == 0 {
return r
}
target := r.getParentValue()
for target.Kind() == reflect.Ptr || target.Kind() == reflect.Interface {
if target.IsNil() {
panic("rfx: cannot append to nil value")
}
target = target.Elem()
}
if !target.IsValid() || target.Kind() != reflect.Slice {
panic("rfx: Append only supports slice type")
}
// 一次性构造所有要追加的元素,然后调用一次 reflect.Append
elemType := target.Type().Elem()
newValues := make([]reflect.Value, len(items))
for i, item := range items {
newElem := reflect.New(elemType).Elem()
if !r.setValue(newElem, item) {
panic("rfx: failed to append item to slice")
}
newValues[i] = newElem
}
target.Set(reflect.Append(target, newValues...))
return r
}
// setNestedValue 递归设置嵌套值,特殊处理 map 中的 struct
func (r *rfx) setNestedValue(current reflect.Value, keys []string, v any) bool {
// 解引用指针和接口
for current.Kind() == reflect.Ptr || current.Kind() == reflect.Interface {
if current.IsNil() {
return false
}
current = current.Elem()
}
if !current.IsValid() {
return false
}
// 如果只剩一个键,直接设置
if len(keys) == 1 {
if !current.CanSet() {
return false
}
return r.setFieldValue(current, keys[0], v)
}
// 多个键的情况
firstKey := keys[0]
remainingKeys := keys[1:]
switch current.Kind() {
case reflect.Struct:
field := tryStructFieldValue(current, firstKey)
if !field.IsValid() {
return false
}
return r.setNestedValue(field, remainingKeys, v)
case reflect.Map:
// Map 的特殊处理
// 使用 tryMapFieldKey 获取实际的键
actualKey := tryMapFieldKey(current, firstKey)
if !actualKey.IsValid() {
return false
}
mapValue := current.MapIndex(actualKey)
if !mapValue.IsValid() {
return false
}
// 解开 interface 包装获取实际的值
actualValue := mapValue
for actualValue.Kind() == reflect.Interface && !actualValue.IsNil() {
actualValue = actualValue.Elem()
}
// 创建 map 值的副本以便修改
valueCopy := reflect.New(actualValue.Type()).Elem()
valueCopy.Set(actualValue)
// 在副本上递归设置值
if !r.setNestedValue(valueCopy, remainingKeys, v) {
return false
}
// 将修改后的值设置回 map,使用实际找到的键
current.SetMapIndex(actualKey, valueCopy)
return true
case reflect.Slice, reflect.Array:
idx, err := strconv.Atoi(firstKey)
if err != nil || idx < 0 || idx >= current.Len() {
return false
}
elem := current.Index(idx)
if !elem.IsValid() {
return false
}
return r.setNestedValue(elem, remainingKeys, v)
}
return false
}
// getParentValue 获取父级值的辅助方法
func (r *rfx) getParentValue(p ...string) reflect.Value {
if len(p) == 0 {
v := r.value
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.IsNil() {
return reflect.Value{}
}
v = v.Elem()
}
return v
}
return getValueByPath(r.value, p...)
}
// setFieldValue 设置字段值的辅助方法
func (r *rfx) setFieldValue(target reflect.Value, key string, v any) bool {
for target.Kind() == reflect.Ptr || target.Kind() == reflect.Interface {
if target.IsNil() {
return false
}
target = target.Elem()
}
switch target.Kind() {
case reflect.Struct:
field := tryStructFieldValue(target, key)
if !field.IsValid() || !field.CanSet() {
return false
}
return r.setValue(field, v)
case reflect.Map:
if target.IsNil() {
target.Set(reflect.MakeMap(target.Type()))
}
// 先尝试使用 tryMapFieldKey 检查字段是否已存在并获取实际的键
actualKey := tryMapFieldKey(target, key)
if actualKey.IsValid() {
// 字段已存在,创建新值用于设置
newValue := reflect.New(target.Type().Elem()).Elem()
if !r.setValue(newValue, v) {
return false
}
target.SetMapIndex(actualKey, newValue)
return true
}
// 字段不存在,创建新的 map 值
// 处理 nil 值的情况
if v == nil {
target.SetMapIndex(reflect.ValueOf(key), reflect.Zero(target.Type().Elem()))
return true
}
val := reflect.ValueOf(v)
if !val.Type().AssignableTo(target.Type().Elem()) {
// 尝试转换
if val.Type().ConvertibleTo(target.Type().Elem()) {
val = val.Convert(target.Type().Elem())
} else {
return false
}
}
target.SetMapIndex(reflect.ValueOf(key), val)
return true
case reflect.Slice:
idx, err := strconv.Atoi(key)
if err != nil {
return false
}
// 对于切片,支持使用索引 -1 追加新元素(插入到切片前面)
if idx == -1 {
elemType := target.Type().Elem()
newElem := reflect.New(elemType).Elem()
if !r.setValue(newElem, v) {
return false
}
// 将新元素放在前面,原有元素顺序后移
newSlice := reflect.MakeSlice(target.Type(), 0, target.Len()+1)
newSlice = reflect.Append(newSlice, newElem)
newSlice = reflect.AppendSlice(newSlice, target)
target.Set(newSlice)
return true
}
if idx < 0 || idx >= target.Len() {
return false
}
elem := target.Index(idx)
if !elem.CanSet() {
return false
}
return r.setValue(elem, v)
case reflect.Array:
idx, err := strconv.Atoi(key)
if err != nil || idx < 0 || idx >= target.Len() {
return false
}
elem := target.Index(idx)
if !elem.CanSet() {
return false
}
return r.setValue(elem, v)
}
return false
}
// setValue 设置值的辅助方法
// 使用 cast 库进行智能类型转换,支持更多的转换场景
func (r *rfx) setValue(field reflect.Value, v any) bool {
val, _, err := normalizeInputValue(v)
if err != nil {
return false
}
targetType := field.Type()
if !val.IsValid() {
val = reflect.Zero(targetType)
}
// 如果 val 有效,进行正常的类型处理
// 统一解开最外层的 interface 包装,便于后续根据底层实际类型做处理
for val.Kind() == reflect.Interface && !val.IsNil() {
val = val.Elem()
}
// 尝试直接赋值(类型完全匹配)
if val.Type().AssignableTo(targetType) {
field.Set(val)
return true
}
// 如果源值是指针但目标不是指针,尝试解引用后再赋值
if val.Kind() == reflect.Ptr && !val.IsNil() && targetType.Kind() != reflect.Ptr {
derefVal := val.Elem()
if derefVal.Type().AssignableTo(targetType) {
field.Set(derefVal)
return true
}
// 解引用后继续使用下面的逻辑处理
val = derefVal
}
switch targetType.Kind() {
case reflect.Ptr:
// 处理指针类型
// 如果传入的值已经是指针类型,尝试直接赋值
if val.Type().AssignableTo(targetType) {
field.Set(val)
return true
}
// 如果传入的值不是指针,创建新指针并设置值
elemType := targetType.Elem()
newPtr := reflect.New(elemType)
// 递归设置指针指向的值
if !r.setValue(newPtr.Elem(), v) {
return false
}
field.Set(newPtr)
return true
case reflect.Slice: // 处理切片类型,支持从通用切片(如 []any)转换
if val.Kind() != reflect.Slice && val.Kind() != reflect.Array {
return false
}
newSlice := reflect.MakeSlice(targetType, val.Len(), val.Len())
for i := 0; i < val.Len(); i++ {
if !r.setValue(newSlice.Index(i), val.Index(i)) {
return false
}
}
field.Set(newSlice)
return true
case reflect.Struct:
// 遍历目标结构体的字段,从源值(结构体或 map)中按字段名取值并设置
// 仅支持从 struct 或 map 填充
if val.Kind() != reflect.Struct && val.Kind() != reflect.Map {
return false
}
fieldType := field.Type()
for i := 0; i < fieldType.NumField(); i++ {
dstField := field.Field(i)
if !dstField.CanSet() {
continue
}
valField := getValueByPath(val, fieldType.Field(i).Name)
if !valField.IsValid() {
continue
}
// 使用 setValue 复用现有的类型转换逻辑,忽略单个字段失败
if !r.setValue(dstField, valField) {
return false
}
}
return true
}
// 优先使用 cast 进行智能类型转换
// 这样可以处理 string <-> number, number <-> bool 等常见转换
var converted any
switch targetType.Kind() {
case reflect.Bool:
converted, err = cast.ToBoolE(v)
case reflect.Int:
converted, err = cast.ToIntE(v)
case reflect.Int8:
converted, err = cast.ToInt8E(v)
case reflect.Int16:
converted, err = cast.ToInt16E(v)
case reflect.Int32:
converted, err = cast.ToInt32E(v)
case reflect.Int64:
converted, err = cast.ToInt64E(v)
case reflect.Uint:
converted, err = cast.ToUintE(v)
case reflect.Uint8:
converted, err = cast.ToUint8E(v)
case reflect.Uint16:
converted, err = cast.ToUint16E(v)
case reflect.Uint32:
converted, err = cast.ToUint32E(v)
case reflect.Uint64:
converted, err = cast.ToUint64E(v)
case reflect.Float32:
converted, err = cast.ToFloat32E(v)
case reflect.Float64:
converted, err = cast.ToFloat64E(v)
case reflect.String:
converted, err = cast.ToStringE(v)
default:
return false
}
if err != nil {
// 如果 cast 失败,尝试标准的反射类型转换作为后备
if val.IsValid() && val.Type().ConvertibleTo(field.Type()) {
field.Set(val.Convert(field.Type()))
return true
}
return false
}
field.Set(reflect.ValueOf(converted))
return true
}
// Delete 删除指定路径的值,支持链式调用
// 如果删除失败会 panic
func (r *rfx) Delete(p ...string) R {
if len(p) == 0 {
panic("rfx: empty path")
}
// 展开路径
keys := expandPath(p...)
if len(keys) == 0 {
panic("rfx: empty path")
}
target := r.getParentValue(keys[:len(keys)-1]...)
if !target.IsValid() {
panic(fmt.Sprintf("rfx: invalid path '%s'", strings.Join(keys[:len(keys)-1], ".")))
}
lastKey := keys[len(keys)-1]
for target.Kind() == reflect.Ptr || target.Kind() == reflect.Interface {
if target.IsNil() {
panic(fmt.Sprintf("rfx: nil value at path '%s'", strings.Join(keys[:len(keys)-1], ".")))
}
target = target.Elem()
}
switch target.Kind() {
case reflect.Map:
target.SetMapIndex(reflect.ValueOf(lastKey), reflect.Value{})
return r
case reflect.Slice:
idx, err := strconv.Atoi(lastKey)
if err != nil {
panic(fmt.Sprintf("rfx: invalid slice index '%s'", lastKey))
}
if idx < 0 || idx >= target.Len() {
panic(fmt.Sprintf("rfx: slice index out of range: %d", idx))
}
// 删除切片元素
newSlice := reflect.AppendSlice(
target.Slice(0, idx),
target.Slice(idx+1, target.Len()),
)
target.Set(newSlice)
return r
default:
panic(fmt.Sprintf("rfx: cannot delete from type %s", target.Kind()))
}
}
// Exists 检查指定路径的值是否存在
func (r *rfx) Exists(p ...string) bool {
return getValueByPath(r.value, p...).IsValid()
}
// Array 将当前值转换为 R 切片
func (r *rfx) Array() []R {
v := r.value
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.IsNil() {
return nil
}
v = v.Elem()
}
if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
return nil
}
result := make([]R, v.Len())
for i := 0; i < v.Len(); i++ {
result[i] = &rfx{value: v.Index(i)}
}
return result
}
// keys 返回当前映射或结构体的所有键名
func (r *rfx) Keys() []string {
v := r.value
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.IsNil() {
return nil
}
v = v.Elem()
}
switch v.Kind() {
case reflect.Map:
keys := v.MapKeys()
result := make([]string, len(keys))
for i, k := range keys {
result[i] = fmt.Sprint(k.Interface())
}
return result
case reflect.Struct:
t := v.Type()
result := make([]string, t.NumField())
for i := 0; i < t.NumField(); i++ {
result[i] = t.Field(i).Name
}
return result
}
return nil
}
// Raw 返回底层的 reflect.Value
func (r *rfx) Raw() reflect.Value {
return r.value
}
// Lookup 根据路径查找并返回对应值的访问器
func (r *rfx) Lookup(path string) (valuex.Accessor, bool) {
v := r.Get(path)
if v.Exists() {
return v, true
}
return valuex.Nil, false
}
// Ptr 返回指向当前值的指针
func (r *rfx) Ptr() any {
v := r.value
if v.Kind() == reflect.Ptr {
return v.Interface()
}
if v.CanAddr() {
return v.Addr().Interface()
}
return nil
}
// Any 将当前值转换为 any 类型
func (r *rfx) Any() any {
v := r.value
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.IsNil() {
return nil
}
v = v.Elem()
}
if !v.IsValid() {
return nil
}
return v.Interface()
}
// Bool 将当前值转换为 bool 类型
func (r *rfx) Bool() bool {
result, err := cast.ToBoolE(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to bool: %v", err))
}
return result
}
// Float64 将当前值转换为 float64 类型
func (r *rfx) Float64() float64 {
result, err := cast.ToFloat64E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to float64: %v", err))
}
return result
}
// Float32 将当前值转换为 float32 类型
func (r *rfx) Float32() float32 {
result, err := cast.ToFloat32E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to float32: %v", err))
}
return result
}
// Int64 将当前值转换为 int64 类型
func (r *rfx) Int64() int64 {
result, err := cast.ToInt64E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to int64: %v", err))
}
return result
}
// Int32 将当前值转换为 int32 类型
func (r *rfx) Int32() int32 {
result, err := cast.ToInt32E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to int32: %v", err))
}
return result
}
// Int16 将当前值转换为 int16 类型
func (r *rfx) Int16() int16 {
result, err := cast.ToInt16E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to int16: %v", err))
}
return result
}
// Int8 将当前值转换为 int8 类型
func (r *rfx) Int8() int8 {
result, err := cast.ToInt8E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to int8: %v", err))
}
return result
}
// Int 将当前值转换为 int 类型
func (r *rfx) Int() int {
result, err := cast.ToIntE(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to int: %v", err))
}
return result
}
// Uint 将当前值转换为 uint 类型
func (r *rfx) Uint() uint {
result, err := cast.ToUintE(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to uint: %v", err))
}
return result
}
// Uint64 将当前值转换为 uint64 类型
func (r *rfx) Uint64() uint64 {
result, err := cast.ToUint64E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to uint64: %v", err))
}
return result
}
// Uint32 将当前值转换为 uint32 类型
func (r *rfx) Uint32() uint32 {
result, err := cast.ToUint32E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to uint32: %v", err))
}
return result
}
// Uint16 将当前值转换为 uint16 类型
func (r *rfx) Uint16() uint16 {
result, err := cast.ToUint16E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to uint16: %v", err))
}
return result
}
// Uint8 将当前值转换为 uint8 类型
func (r *rfx) Uint8() uint8 {
result, err := cast.ToUint8E(r.Any())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to uint8: %v", err))
}
return result
}
// String 将当前值转换为 string 类型
func (r *rfx) String() string {
data := r.Any()
result, err := cast.ToStringE(data)
if err != nil {
if b, e := json.Marshal(data); e == nil {
result = string(b)
} else {
panic(fmt.Sprintf("rfx: failed to convert to string: %v", err))
}
}
return result
}
// StringMapString 将当前值转换为 map[string]string 类型
func (r *rfx) StringMapString() map[string]string {
data := r.Any()
// 首先尝试使用 cast 进行转换
result, err := cast.ToStringMapStringE(data)
if err == nil {
return result
}
// cast 失败后,尝试自定义转换逻辑
defer func() {
if p := recover(); p != nil {
panic(fmt.Sprintf("rfx: failed to convert to map[string]string, cast error: %v, custom conversion error: %v", err, p))
}
}()
result = make(map[string]string)
for _, k := range r.Keys() {
result[k] = r.Get(k).String()
}
return result
}
// StringMapStringSlice 将当前值转换为 map[string][]string 类型
func (r *rfx) StringMapStringSlice() map[string][]string {
data := r.Any()
// 首先尝试使用 cast 进行转换
result, err := cast.ToStringMapStringSliceE(data)
if err == nil {
return result
}
// cast 失败后,尝试自定义转换逻辑
defer func() {
if p := recover(); p != nil {
panic(fmt.Sprintf("rfx: failed to convert to map[string][]string, cast error: %v, custom conversion error: %v", err, p))
}
}()
result = make(map[string][]string)
for _, k := range r.Keys() {
result[k] = r.Get(k).StringSlice()
}
return result
}
// StringMapBool 将当前值转换为 map[string]bool 类型
func (r *rfx) StringMapBool() map[string]bool {
data := r.Any()
// 首先尝试使用 cast 进行转换
result, err := cast.ToStringMapBoolE(data)
if err == nil {
return result
}
// cast 失败后,尝试自定义转换逻辑
defer func() {
if p := recover(); p != nil {
panic(fmt.Sprintf("rfx: failed to convert to map[string]bool, cast error: %v, custom conversion error: %v", err, p))
}
}()
result = make(map[string]bool)
for _, k := range r.Keys() {
result[k] = r.Get(k).Bool()
}
return result
}
// StringMapInt 将当前值转换为 map[string]int 类型
func (r *rfx) StringMapInt() map[string]int {
data := r.Any()
// 首先尝试使用 cast 进行转换
result, err := cast.ToStringMapIntE(data)
if err == nil {
return result
}
// cast 失败后,尝试自定义转换逻辑
defer func() {
if p := recover(); p != nil {
panic(fmt.Sprintf("rfx: failed to convert to map[string]int, cast error: %v, custom conversion error: %v", err, p))
}
}()
result = make(map[string]int)
for _, k := range r.Keys() {
result[k] = r.Get(k).Int()
}
return result
}
// StringMapInt64 将当前值转换为 map[string]int64 类型
func (r *rfx) StringMapInt64() map[string]int64 {
data := r.Any()
// 首先尝试使用 cast 进行转换
result, err := cast.ToStringMapInt64E(data)
if err == nil {
return result
}
// cast 失败后,尝试自定义转换逻辑
defer func() {
if p := recover(); p != nil {
panic(fmt.Sprintf("rfx: failed to convert to map[string]int64, cast error: %v, custom conversion error: %v", err, p))
}
}()
result = make(map[string]int64)
for _, k := range r.Keys() {
result[k] = r.Get(k).Int64()
}
return result
}
// StringMap 将当前值转换为 map[string]any 类型
func (r *rfx) StringMap() map[string]any {
data := r.Any()
// 首先尝试使用 cast 进行转换
result, err := cast.ToStringMapE(data)
if err == nil {
return result
}
// cast 失败后,尝试自定义转换逻辑
defer func() {
if p := recover(); p != nil {
panic(fmt.Sprintf("rfx: failed to convert to map[string]any, cast error: %v, custom conversion error: %v", err, p))
}
}()
result = make(map[string]any)
for _, k := range r.Keys() {
result[k] = r.Get(k).Any()
}
return result
}
// Slice 将当前值转换为 []any 切片
func (r *rfx) Slice() []any {
v := r.value
for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
if v.IsNil() {
return nil
}
v = v.Elem()
}
if !v.IsValid() || (v.Kind() != reflect.Slice && v.Kind() != reflect.Array) {
return nil
}
result := make([]any, v.Len())
for i := 0; i < v.Len(); i++ {
elem := v.Index(i)
for elem.Kind() == reflect.Ptr || elem.Kind() == reflect.Interface {
if elem.IsNil() {
break
}
elem = elem.Elem()
}
if elem.IsValid() {
result[i] = elem.Interface()
}
}
return result
}
// BoolSlice 将当前值转换为 []bool 切片
func (r *rfx) BoolSlice() []bool {
result, err := cast.ToBoolSliceE(r.Slice())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to []bool: %v", err))
}
return result
}
// StringSlice 将当前值转换为 []string 切片
func (r *rfx) StringSlice() []string {
result, err := cast.ToStringSliceE(r.Slice())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to []string: %v", err))
}
return result
}
// IntSlice 将当前值转换为 []int 切片
func (r *rfx) IntSlice() []int {
result, err := cast.ToIntSliceE(r.Slice())
if err != nil {
panic(fmt.Sprintf("rfx: failed to convert to []int: %v", err))
}
return result
}
// MarshalJSON 实现 json.Marshaler 接口
// 将当前值序列化为 JSON 字节数组
func (r *rfx) MarshalJSON() ([]byte, error) {
return json.Marshal(r.Any())
}
// UnmarshalJSON 实现 json.Unmarshaler 接口
// 从 JSON 字节数组反序列化到当前值
func (r *rfx) UnmarshalJSON(data []byte) error {
// 先解析到 any 类型
var v any
if err := json.Unmarshal(data, &v); err != nil {
return err
}
// 获取当前值的实际类型
target := r.value
for target.Kind() == reflect.Ptr || target.Kind() == reflect.Interface {
if target.IsNil() {
break
}
target = target.Elem()
}
// 如果当前值无效或为 nil创建一个新的 map[string]any
if !target.IsValid() || !target.CanSet() {
r.value = reflect.ValueOf(&v).Elem()
return nil
}
// 尝试将解析的值设置到当前值
newValue := reflect.ValueOf(v)
if newValue.Type().AssignableTo(target.Type()) {
target.Set(newValue)
return nil
}
// 如果类型不匹配,尝试使用 setValue 进行转换
if !r.setValue(target, v) {
return fmt.Errorf("rfx: failed to unmarshal JSON into type %s", target.Type())
}
return nil
}