fix: unmarshal

This commit is contained in:
yusing 2025-04-14 06:32:16 +08:00
parent 2ec1de96d5
commit eb7495b02a
2 changed files with 34 additions and 29 deletions

View file

@ -308,6 +308,20 @@ func isIntFloat(t reflect.Kind) bool {
return t >= reflect.Bool && t <= reflect.Float64 return t >= reflect.Bool && t <= reflect.Float64
} }
func itoa(v reflect.Value) string {
switch v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(v.Int(), 10)
case reflect.Bool:
return strconv.FormatBool(v.Bool())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return strconv.FormatUint(v.Uint(), 10)
case reflect.Float32, reflect.Float64:
return strconv.FormatFloat(v.Float(), 'f', -1, 64)
}
panic("invalid call on itoa")
}
// Convert attempts to convert the src to dst. // Convert attempts to convert the src to dst.
// //
// If src is a map, it is deserialized into dst. // If src is a map, it is deserialized into dst.
@ -365,20 +379,12 @@ func Convert(src reflect.Value, dst reflect.Value) gperr.Error {
} }
case isIntFloat(srcKind): case isIntFloat(srcKind):
if dst.Kind() == reflect.String { if dst.Kind() == reflect.String {
var strV string dst.Set(reflect.ValueOf(itoa(src)))
switch {
case src.CanInt():
strV = strconv.FormatInt(src.Int(), 10)
case srcKind == reflect.Bool:
strV = strconv.FormatBool(src.Bool())
case src.CanUint():
strV = strconv.FormatUint(src.Uint(), 10)
case src.CanFloat():
strV = strconv.FormatFloat(src.Float(), 'f', -1, 64)
}
dst.Set(reflect.ValueOf(strV))
return nil return nil
} }
if dst.Addr().Type().Implements(typeStrParser) {
return Convert(reflect.ValueOf(itoa(src)), dst)
}
if !isIntFloat(dstT.Kind()) || !src.CanConvert(dstT) { if !isIntFloat(dstT.Kind()) || !src.CanConvert(dstT) {
return ErrUnsupportedConversion.Subjectf("%s to %s", srcT, dstT) return ErrUnsupportedConversion.Subjectf("%s to %s", srcT, dstT)
} }
@ -445,7 +451,8 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
dst = dst.Elem() dst = dst.Elem()
dstT = dst.Type() dstT = dst.Type()
} }
if dst.Kind() == reflect.String { dstKind := dst.Kind()
if dstKind == reflect.String {
dst.SetString(src) dst.SetString(src)
return return
} }
@ -482,7 +489,7 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
setSameOrEmbedddType(reflect.ValueOf(ipnet).Elem(), dst) setSameOrEmbedddType(reflect.ValueOf(ipnet).Elem(), dst)
return return
} }
if dstKind := dst.Kind(); isIntFloat(dstKind) { if isIntFloat(dstKind) {
var i any var i any
var err error var err error
switch { switch {
@ -512,7 +519,14 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
} }
// yaml like // yaml like
var tmp any var tmp any
switch dst.Kind() { switch dstKind {
case reflect.Map, reflect.Struct:
rawMap := make(SerializedObject)
err := yaml.Unmarshal([]byte(src), &rawMap)
if err != nil {
return true, gperr.Wrap(err)
}
tmp = rawMap
case reflect.Slice: case reflect.Slice:
src = strings.TrimSpace(src) src = strings.TrimSpace(src)
isMultiline := strings.ContainsRune(src, '\n') isMultiline := strings.ContainsRune(src, '\n')
@ -538,13 +552,6 @@ func ConvertString(src string, dst reflect.Value) (convertible bool, convErr gpe
return true, gperr.Wrap(err) return true, gperr.Wrap(err)
} }
tmp = sl tmp = sl
case reflect.Map, reflect.Struct:
rawMap := make(SerializedObject)
err := yaml.Unmarshal([]byte(src), &rawMap)
if err != nil {
return true, gperr.Wrap(err)
}
tmp = rawMap
default: default:
return false, nil return false, nil
} }

View file

@ -7,9 +7,7 @@ import (
"reflect" "reflect"
"strconv" "strconv"
"testing" "testing"
"time"
"github.com/yusing/go-proxy/internal/utils/strutils"
. "github.com/yusing/go-proxy/internal/utils/testing" . "github.com/yusing/go-proxy/internal/utils/testing"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )