Browse Source

chore: optimize `ParseJsonBody` (#1353)

* chore: optimize `ParseJsonBody`

* chore: optimize `ParseJsonBody`

* fix: fix a test

* chore: optimize `ParseJsonBody`

* fix a test

* chore: add comment
chenquan 3 years ago
parent
commit
263e426ae1
3 changed files with 39 additions and 14 deletions
  1. 5 0
      core/mapping/jsonunmarshaler.go
  2. 4 4
      rest/httpx/requests.go
  3. 30 10
      rest/httpx/requests_test.go

+ 5 - 0
core/mapping/jsonunmarshaler.go

@@ -15,6 +15,11 @@ func UnmarshalJsonBytes(content []byte, v interface{}) error {
 	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.
 func UnmarshalJsonReader(reader io.Reader, v interface{}) error {
 	return unmarshalJsonReader(reader, v, jsonUnmarshaler)

+ 4 - 4
rest/httpx/requests.go

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

+ 30 - 10
rest/httpx/requests_test.go

@@ -196,18 +196,38 @@ Content-Disposition: form-data; name="age"
 }
 
 func TestParseJsonBody(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, ApplicationJson)
+	t.Run("has 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, 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) {