chore: optimize `ParseJsonBody` (#1353)

* chore: optimize `ParseJsonBody`

* chore: optimize `ParseJsonBody`

* fix: fix a test

* chore: optimize `ParseJsonBody`

* fix a test

* chore: add comment
master
chenquan 3 years ago committed by GitHub
parent d5e493383a
commit 263e426ae1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -15,6 +15,11 @@ func UnmarshalJsonBytes(content []byte, v interface{}) error {
return unmarshalJsonBytes(content, v, jsonUnmarshaler) return unmarshalJsonBytes(content, v, jsonUnmarshaler)
} }
// UnmarshalJsonMap unmarshals content from m into v.
func UnmarshalJsonMap(m map[string]interface{}, v interface{}) error {
return jsonUnmarshaler.Unmarshal(m, v)
}
// UnmarshalJsonReader unmarshals content from reader into v. // UnmarshalJsonReader unmarshals content from reader into v.
func UnmarshalJsonReader(reader io.Reader, v interface{}) error { func UnmarshalJsonReader(reader io.Reader, v interface{}) error {
return unmarshalJsonReader(reader, v, jsonUnmarshaler) return unmarshalJsonReader(reader, v, jsonUnmarshaler)

@ -14,7 +14,6 @@ const (
formKey = "form" formKey = "form"
pathKey = "path" pathKey = "path"
headerKey = "header" headerKey = "header"
emptyJson = "{}"
maxMemory = 32 << 20 // 32MB maxMemory = 32 << 20 // 32MB
maxBodyLen = 8 << 20 // 8MB maxBodyLen = 8 << 20 // 8MB
separator = ";" separator = ";"
@ -26,6 +25,8 @@ var (
pathUnmarshaler = mapping.NewUnmarshaler(pathKey, mapping.WithStringValues()) pathUnmarshaler = mapping.NewUnmarshaler(pathKey, mapping.WithStringValues())
headerUnmarshaler = mapping.NewUnmarshaler(headerKey, mapping.WithStringValues(), headerUnmarshaler = mapping.NewUnmarshaler(headerKey, mapping.WithStringValues(),
mapping.WithCanonicalKeyFunc(textproto.CanonicalMIMEHeaderKey)) mapping.WithCanonicalKeyFunc(textproto.CanonicalMIMEHeaderKey))
emptyMap = map[string]interface{}{}
) )
// Parse parses the request. // Parse parses the request.
@ -109,11 +110,10 @@ func ParseJsonBody(r *http.Request, v interface{}) error {
var reader io.Reader var reader io.Reader
if withJsonBody(r) { if withJsonBody(r) {
reader = io.LimitReader(r.Body, maxBodyLen) reader = io.LimitReader(r.Body, maxBodyLen)
} else { return mapping.UnmarshalJsonReader(reader, v)
reader = strings.NewReader(emptyJson)
} }
return mapping.UnmarshalJsonReader(reader, v) return mapping.UnmarshalJsonMap(emptyMap, v)
} }
// ParsePath parses the symbols reside in url path. // ParsePath parses the symbols reside in url path.

@ -196,18 +196,38 @@ Content-Disposition: form-data; name="age"
} }
func TestParseJsonBody(t *testing.T) { func TestParseJsonBody(t *testing.T) {
var v struct {
Name string `json:"name"`
Age int `json:"age"`
}
body := `{"name":"kevin", "age": 18}` t.Run("has body", func(t *testing.T) {
r := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(body))
r.Header.Set(ContentType, ApplicationJson) 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, ApplicationJson)
assert.Nil(t, Parse(r, &v))
assert.Equal(t, "kevin", v.Name)
assert.Equal(t, 18, v.Age)
})
t.Run("hasn't body", func(t *testing.T) {
var v struct {
Name string `json:"name,optional"`
Age int `json:"age,optional"`
}
r := httptest.NewRequest(http.MethodGet, "/", nil)
assert.Nil(t, Parse(r, &v))
assert.Equal(t, "", v.Name)
assert.Equal(t, 0, v.Age)
})
assert.Nil(t, Parse(r, &v))
assert.Equal(t, "kevin", v.Name)
assert.Equal(t, 18, v.Age)
} }
func TestParseRequired(t *testing.T) { func TestParseRequired(t *testing.T) {

Loading…
Cancel
Save