diff --git a/mapstructure.go b/mapstructure.go index 9087fd96..26c3d782 100644 --- a/mapstructure.go +++ b/mapstructure.go @@ -814,7 +814,7 @@ func (d *Decoder) decodeInt(name string, data any, val reflect.Value) error { }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": - jn := data.(json.Number) + jn := dataVal.Interface().(json.Number) i, err := jn.Int64() if err != nil { return newDecodeError(name, &ParseError{ @@ -885,7 +885,7 @@ func (d *Decoder) decodeUint(name string, data any, val reflect.Value) error { }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": - jn := data.(json.Number) + jn := dataVal.Interface().(json.Number) i, err := strconv.ParseUint(string(jn), 0, 64) if err != nil { return newDecodeError(name, &ParseError{ @@ -976,7 +976,7 @@ func (d *Decoder) decodeFloat(name string, data any, val reflect.Value) error { }) } case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": - jn := data.(json.Number) + jn := dataVal.Interface().(json.Number) i, err := jn.Float64() if err != nil { return newDecodeError(name, &ParseError{ diff --git a/mapstructure_test.go b/mapstructure_test.go index baf40dfe..a47c5d42 100644 --- a/mapstructure_test.go +++ b/mapstructure_test.go @@ -409,6 +409,42 @@ func TestBasicTypes(t *testing.T) { } } +func TestDecode_JSONNumberPointer(t *testing.T) { + t.Parallel() + + for _, tc := range []struct { + name string + input json.Number + want any + wantErr bool + }{ + {"int64", "-42", int64(-42), false}, + {"uint64", "9223372036854775809", uint64(9223372036854775809), false}, + {"float64", "42.5", float64(42.5), false}, + {"invalid_int64", "invalid", int64(0), true}, + {"invalid_uint64", "invalid", uint64(0), true}, + {"invalid_float64", "invalid", float64(0), true}, + } { + t.Run(tc.name, func(t *testing.T) { + result := reflect.New(reflect.TypeOf(tc.want)) + err := Decode(&tc.input, result.Interface()) + if tc.wantErr { + var parseErr *ParseError + if !errors.As(err, &parseErr) { + t.Fatalf("expected ParseError, got %v", err) + } + return + } + if err != nil { + t.Fatal(err) + } + if got := result.Elem().Interface(); !reflect.DeepEqual(got, tc.want) { + t.Fatalf("got %#v, want %#v", got, tc.want) + } + }) + } +} + func TestBasic_IntWithFloat(t *testing.T) { t.Parallel()