Skip to content

Commit

Permalink
fix #1729 (#1783)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevwan committed Apr 13, 2022
1 parent ba8ac97 commit ecc3653
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 2 deletions.
16 changes: 14 additions & 2 deletions core/mapping/unmarshaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ func (u *Unmarshaler) processFieldPrimitiveWithJSONNumber(field reflect.StructFi
return err
}

if iValue < 0 {
return fmt.Errorf("unmarshal %q with bad value %q", fullName, v.String())
}

value.SetUint(uint64(iValue))
case reflect.Float32, reflect.Float64:
fValue, err := v.Float64()
Expand Down Expand Up @@ -727,10 +731,10 @@ func fillWithSameType(field reflect.StructField, value reflect.Value, mapValue i
if field.Type.Kind() == reflect.Ptr {
baseType := Deref(field.Type)
target := reflect.New(baseType).Elem()
target.Set(reflect.ValueOf(mapValue))
setSameKindValue(baseType, target, mapValue)
value.Set(target.Addr())
} else {
value.Set(reflect.ValueOf(mapValue))
setSameKindValue(field.Type, value, mapValue)
}

return nil
Expand Down Expand Up @@ -805,3 +809,11 @@ func readKeys(key string) []string {

return keys
}

func setSameKindValue(targetType reflect.Type, target reflect.Value, value interface{}) {
if reflect.ValueOf(value).Type().AssignableTo(targetType) {
target.Set(reflect.ValueOf(value))
} else {
target.Set(reflect.ValueOf(value).Convert(targetType))
}
}
80 changes: 80 additions & 0 deletions core/mapping/unmarshaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2660,6 +2660,86 @@ func TestUnmarshalJsonWithoutKey(t *testing.T) {
assert.Equal(t, "2", res.B)
}

func TestUnmarshalJsonUintNegative(t *testing.T) {
payload := `{"a": -1}`
var res struct {
A uint `json:"a"`
}
reader := strings.NewReader(payload)
err := UnmarshalJsonReader(reader, &res)
assert.NotNil(t, err)
}

func TestUnmarshalJsonDefinedInt(t *testing.T) {
type Int int
var res struct {
A Int `json:"a"`
}
payload := `{"a": -1}`
reader := strings.NewReader(payload)
err := UnmarshalJsonReader(reader, &res)
assert.Nil(t, err)
assert.Equal(t, Int(-1), res.A)
}

func TestUnmarshalJsonDefinedString(t *testing.T) {
type String string
var res struct {
A String `json:"a"`
}
payload := `{"a": "foo"}`
reader := strings.NewReader(payload)
err := UnmarshalJsonReader(reader, &res)
assert.Nil(t, err)
assert.Equal(t, String("foo"), res.A)
}

func TestUnmarshalJsonDefinedStringPtr(t *testing.T) {
type String string
var res struct {
A *String `json:"a"`
}
payload := `{"a": "foo"}`
reader := strings.NewReader(payload)
err := UnmarshalJsonReader(reader, &res)
assert.Nil(t, err)
assert.Equal(t, String("foo"), *res.A)
}

func TestUnmarshalJsonReaderComplex(t *testing.T) {
type (
MyInt int
MyTxt string
MyTxtArray []string

Req struct {
MyInt MyInt `json:"my_int"` // int.. ok
MyTxtArray MyTxtArray `json:"my_txt_array"`
MyTxt MyTxt `json:"my_txt"` // but string is not assignable
Int int `json:"int"`
Txt string `json:"txt"`
}
)
body := `{
"my_int": 100,
"my_txt_array": [
"a",
"b"
],
"my_txt": "my_txt",
"int": 200,
"txt": "txt"
}`
var req Req
err := UnmarshalJsonReader(strings.NewReader(body), &req)
assert.Nil(t, err)
assert.Equal(t, MyInt(100), req.MyInt)
assert.Equal(t, MyTxt("my_txt"), req.MyTxt)
assert.EqualValues(t, MyTxtArray([]string{"a", "b"}), req.MyTxtArray)
assert.Equal(t, 200, req.Int)
assert.Equal(t, "txt", req.Txt)
}

func BenchmarkDefaultValue(b *testing.B) {
for i := 0; i < b.N; i++ {
var a struct {
Expand Down

0 comments on commit ecc3653

Please sign in to comment.