diff --git a/core/mapping/unmarshaler.go b/core/mapping/unmarshaler.go index fb4838c22..8d7d133b5 100644 --- a/core/mapping/unmarshaler.go +++ b/core/mapping/unmarshaler.go @@ -622,13 +622,19 @@ func (u *Unmarshaler) processFieldNotFromString(fieldType reflect.Type, value re return u.fillSliceFromString(fieldType, value, mapValue, fullName) case valueKind == reflect.String && derefedFieldType == durationType: - v, ok := mapValue.(string) - if !ok { - return fmt.Errorf("unexpected type %T, expected a string value for field %s", mapValue, fullName) + v, err := convertToString(mapValue, fullName) + if err != nil { + return err } + return fillDurationValue(fieldType, value, v) case valueKind == reflect.String && typeKind == reflect.Struct && u.implementsUnmarshaler(fieldType): - return u.fillUnmarshalerStruct(fieldType, value, mapValue.(string)) + v, err := convertToString(mapValue, fullName) + if err != nil { + return err + } + + return u.fillUnmarshalerStruct(fieldType, value, v) default: return u.processFieldPrimitive(fieldType, value, mapValue, opts, fullName) } diff --git a/core/mapping/unmarshaler_test.go b/core/mapping/unmarshaler_test.go index ac9efd8ba..d9534962b 100644 --- a/core/mapping/unmarshaler_test.go +++ b/core/mapping/unmarshaler_test.go @@ -13,7 +13,6 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/assert" - "github.com/zeromicro/go-zero/core/jsonx" "github.com/zeromicro/go-zero/core/stringx" ) @@ -215,7 +214,7 @@ func TestUnmarshalDurationUnexpectedError(t *testing.T) { var in inner err = UnmarshalKey(m, &in) assert.Error(t, err) - assert.Contains(t, err.Error(), "unexpected type") + assert.Contains(t, err.Error(), "expect string") } func TestUnmarshalDurationDefault(t *testing.T) { @@ -6010,6 +6009,16 @@ func TestUnmarshal_Unmarshaler(t *testing.T) { }, &v)) assert.Nil(t, v.Foo) }) + + t.Run("json.Number", func(t *testing.T) { + v := struct { + Foo *mockUnmarshaler `json:"name"` + }{} + m := map[string]any{ + "name": json.Number("123"), + } + assert.Error(t, UnmarshalJsonMap(m, &v)) + }) } func TestParseJsonStringValue(t *testing.T) { diff --git a/core/mapping/utils.go b/core/mapping/utils.go index 4995c3634..b59fde7f1 100644 --- a/core/mapping/utils.go +++ b/core/mapping/utils.go @@ -92,6 +92,15 @@ func ValidatePtr(v reflect.Value) error { return nil } +func convertToString(val any, fullName string) (string, error) { + v, ok := val.(string) + if !ok { + return "", fmt.Errorf("expect string for field %s, but got type %T", fullName, val) + } + + return v, nil +} + func convertTypeFromString(kind reflect.Kind, str string) (any, error) { switch kind { case reflect.Bool: