* fix: #2735

* chore: make error consistent
This commit is contained in:
Kevin Wan
2023-01-01 12:21:53 +08:00
committed by GitHub
parent c7a0ec428c
commit cf6c349118
5 changed files with 64 additions and 10 deletions

View File

@@ -34,7 +34,7 @@ func getJsonUnmarshaler(opts ...UnmarshalOption) *Unmarshaler {
}
func unmarshalJsonBytes(content []byte, v interface{}, unmarshaler *Unmarshaler) error {
var m map[string]interface{}
var m interface{}
if err := jsonx.Unmarshal(content, &m); err != nil {
return err
}
@@ -43,7 +43,7 @@ func unmarshalJsonBytes(content []byte, v interface{}, unmarshaler *Unmarshaler)
}
func unmarshalJsonReader(reader io.Reader, v interface{}, unmarshaler *Unmarshaler) error {
var m map[string]interface{}
var m interface{}
if err := jsonx.UnmarshalFromReader(reader, &m); err != nil {
return err
}

View File

@@ -856,8 +856,7 @@ func TestUnmarshalBytesError(t *testing.T) {
}
err := UnmarshalJsonBytes([]byte(payload), &v)
assert.NotNil(t, err)
assert.True(t, strings.Contains(err.Error(), payload))
assert.Equal(t, errTypeMismatch, err)
}
func TestUnmarshalReaderError(t *testing.T) {
@@ -867,9 +866,7 @@ func TestUnmarshalReaderError(t *testing.T) {
Any string
}
err := UnmarshalJsonReader(reader, &v)
assert.NotNil(t, err)
assert.True(t, strings.Contains(err.Error(), payload))
assert.Equal(t, errTypeMismatch, UnmarshalJsonReader(reader, &v))
}
func TestUnmarshalMap(t *testing.T) {
@@ -920,3 +917,16 @@ func TestUnmarshalMap(t *testing.T) {
assert.Equal(t, "foo", v.Any)
})
}
func TestUnmarshalJsonArray(t *testing.T) {
var v []struct {
Name string `json:"name"`
Age int `json:"age"`
}
body := `[{"name":"kevin", "age": 18}]`
assert.NoError(t, UnmarshalJsonBytes([]byte(body), &v))
assert.Equal(t, 1, len(v))
assert.Equal(t, "kevin", v[0].Name)
assert.Equal(t, 18, v[0].Age)
}

View File

@@ -71,8 +71,29 @@ func UnmarshalKey(m map[string]interface{}, v interface{}) error {
}
// Unmarshal unmarshals m into v.
func (u *Unmarshaler) Unmarshal(m map[string]interface{}, v interface{}) error {
return u.UnmarshalValuer(mapValuer(m), v)
func (u *Unmarshaler) Unmarshal(i interface{}, v interface{}) error {
valueType := reflect.TypeOf(v)
if valueType.Kind() != reflect.Ptr {
return errValueNotSettable
}
elemType := valueType.Elem()
switch iv := i.(type) {
case map[string]interface{}:
if elemType.Kind() != reflect.Struct {
return errTypeMismatch
}
return u.UnmarshalValuer(mapValuer(iv), v)
case []interface{}:
if elemType.Kind() != reflect.Slice {
return errTypeMismatch
}
return u.fillSlice(elemType, reflect.ValueOf(v).Elem(), iv)
default:
return errUnsupportedType
}
}
// UnmarshalValuer unmarshals m into v.

View File

@@ -23,7 +23,14 @@ func TestUnmarshalWithFullNameNotStruct(t *testing.T) {
var s map[string]interface{}
content := []byte(`{"name":"xiaoming"}`)
err := UnmarshalJsonBytes(content, &s)
assert.Equal(t, errValueNotStruct, err)
assert.Equal(t, errTypeMismatch, err)
}
func TestUnmarshalValueNotSettable(t *testing.T) {
var s map[string]interface{}
content := []byte(`{"name":"xiaoming"}`)
err := UnmarshalJsonBytes(content, s)
assert.Equal(t, errValueNotSettable, err)
}
func TestUnmarshalWithoutTagName(t *testing.T) {

View File

@@ -223,6 +223,22 @@ func TestParseJsonBody(t *testing.T) {
assert.Equal(t, "", v.Name)
assert.Equal(t, 0, v.Age)
})
t.Run("array body", func(t *testing.T) {
var v []struct {
Name string `json:"name"`
Age int `json:"age"`
}
body := `[{"name":"kevin", "age": 18}]`
r := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(body))
r.Header.Set(ContentType, header.JsonContentType)
assert.NoError(t, ParseJsonBody(r, &v))
assert.Equal(t, 1, len(v))
assert.Equal(t, "kevin", v[0].Name)
assert.Equal(t, 18, v[0].Age)
})
}
func TestParseRequired(t *testing.T) {