👷 Add JSONEncoder and JSONDecoder

pull/1177/head
Kiyon 2021-02-20 16:45:13 +08:00
parent c477128e5b
commit c34ca83c06
6 changed files with 97 additions and 34 deletions

View File

@ -16,6 +16,8 @@ import (
"sync"
"time"
"github.com/gofiber/fiber/v2/utils"
"github.com/gofiber/fiber/v2/internal/encoding/json"
"github.com/valyala/fasthttp"
)
@ -59,6 +61,18 @@ type Client struct {
// NoDefaultUserAgentHeader when set to true, causes the default
// User-Agent header to be excluded from the Request.
NoDefaultUserAgentHeader bool
// When set by an external client of Fiber it will use the provided implementation of a
// JSONMarshal
//
// Allowing for flexibility in using another json library for encoding
JSONEncoder utils.JSONMarshal
// When set by an external client of Fiber it will use the provided implementation of a
// JSONUnmarshal
//
// Allowing for flexibility in using another json library for decoding
JSONDecoder utils.JSONUnmarshal
}
// Get returns a agent with http method GET.
@ -116,6 +130,8 @@ func (c *Client) createAgent(method, url string) *Agent {
a.Name = c.UserAgent
a.NoDefaultUserAgentHeader = c.NoDefaultUserAgentHeader
a.jsonDecoder = c.JSONDecoder
a.jsonEncoder = c.JSONEncoder
if err := a.Parse(); err != nil {
a.errs = append(a.errs, err)
@ -135,6 +151,8 @@ type Agent struct {
formFiles []*FormFile
debugWriter io.Writer
mw multipartWriter
jsonEncoder utils.JSONMarshal
jsonDecoder utils.JSONUnmarshal
maxRedirectsCount int
boundary string
Name string
@ -450,9 +468,13 @@ func (a *Agent) Request(req *Request) *Agent {
// JSON sends a JSON request.
func (a *Agent) JSON(v interface{}) *Agent {
if a.jsonEncoder == nil {
a.jsonEncoder = json.Marshal
}
a.req.Header.SetContentType(MIMEApplicationJSON)
if body, err := json.Marshal(v); err != nil {
if body, err := a.jsonEncoder(v); err != nil {
a.errs = append(a.errs, err)
} else {
a.req.SetBody(body)
@ -658,6 +680,20 @@ func (a *Agent) MaxRedirectsCount(count int) *Agent {
return a
}
// JSONEncoder sets custom json encoder.
func (a *Agent) JSONEncoder(jsonEncoder utils.JSONMarshal) *Agent {
a.jsonEncoder = jsonEncoder
return a
}
// JSONDecoder sets custom json decoder.
func (a *Agent) JSONDecoder(jsonDecoder utils.JSONUnmarshal) *Agent {
a.jsonDecoder = jsonDecoder
return a
}
/************************** End Agent Setting **************************/
// Bytes returns the status code, bytes body and errors of url.
@ -738,9 +774,13 @@ func (a *Agent) String(resp ...*Response) (int, string, []error) {
// Struct returns the status code, bytes body and errors of url.
// And bytes body will be unmarshalled to given v.
func (a *Agent) Struct(v interface{}, resp ...*Response) (code int, body []byte, errs []error) {
if a.jsonDecoder == nil {
a.jsonDecoder = json.Unmarshal
}
code, body, errs = a.Bytes(resp...)
if err := json.Unmarshal(body, v); err != nil {
if err := a.jsonDecoder(body, v); err != nil {
errs = append(errs, err)
}

View File

@ -15,6 +15,8 @@ import (
"testing"
"time"
"github.com/gofiber/fiber/v2/internal/encoding/json"
"github.com/gofiber/fiber/v2/utils"
"github.com/valyala/fasthttp/fasthttputil"
)
@ -532,6 +534,7 @@ func Test_Client_Agent_Json(t *testing.T) {
func Test_Client_Agent_Json_Error(t *testing.T) {
a := Get("http://example.com").
JSONEncoder(json.Marshal).
JSON(complex(1, 1))
_, body, errs := a.String()
@ -947,7 +950,8 @@ func Test_Client_Agent_Struct(t *testing.T) {
var d data
code, body, errs := a.Struct(&d)
code, body, errs := a.JSONDecoder(json.Unmarshal).
Struct(&d)
utils.AssertEqual(t, StatusOK, code)
utils.AssertEqual(t, `{"success"`, string(body))

9
utils/json.go Normal file
View File

@ -0,0 +1,9 @@
package utils
// JSONMarshal returns the JSON encoding of v.
type JSONMarshal func(v interface{}) ([]byte, error)
// JSONUnmarshal parses the JSON-encoded data and stores the result
// in the value pointed to by v. If v is nil or not a pointer,
// Unmarshal returns an InvalidUnmarshalError.
type JSONUnmarshal func(data []byte, v interface{}) error

View File

@ -1,5 +0,0 @@
package utils
// JSONMarshal is the standard definition of representing a Go structure in
// json format
type JSONMarshal func(interface{}) ([]byte, error)

View File

@ -1,26 +0,0 @@
package utils
import (
"encoding/json"
"testing"
)
func TestDefaultJSONEncoder(t *testing.T) {
type SampleStructure struct {
ImportantString string `json:"important_string"`
}
var (
sampleStructure = &SampleStructure{
ImportantString: "Hello World",
}
importantString = `{"important_string":"Hello World"}`
jsonEncoder JSONMarshal = json.Marshal
)
raw, err := jsonEncoder(sampleStructure)
AssertEqual(t, err, nil)
AssertEqual(t, string(raw), importantString)
}

41
utils/json_test.go Normal file
View File

@ -0,0 +1,41 @@
package utils
import (
"encoding/json"
"testing"
)
type sampleStructure struct {
ImportantString string `json:"important_string"`
}
func Test_DefaultJSONEncoder(t *testing.T) {
t.Parallel()
var (
ss = &sampleStructure{
ImportantString: "Hello World",
}
importantString = `{"important_string":"Hello World"}`
jsonEncoder JSONMarshal = json.Marshal
)
raw, err := jsonEncoder(ss)
AssertEqual(t, err, nil)
AssertEqual(t, string(raw), importantString)
}
func Test_DefaultJSONDecoder(t *testing.T) {
t.Parallel()
var (
ss sampleStructure
importantString = []byte(`{"important_string":"Hello World"}`)
jsonDecoder JSONUnmarshal = json.Unmarshal
)
err := jsonDecoder(importantString, &ss)
AssertEqual(t, err, nil)
AssertEqual(t, "Hello World", ss.ImportantString)
}