Repository: go-resty/resty
Pull request #621 (2023-02-27 14:46:00)

client: setters for JSON and XML Marshal/Unmarshal
Today I learned that I can set external JSON library for resty to marshal JSON faster. It wasn't so obvious because I haven't read the docs (let's be honest it's not only me who doesn't read docs), but there was no method for `resty.Client` to override JSON marshal function.

I suggest adding these `Set*` functions because this way they will be available through IDEs auto-completion.

codecov[bot]: # [Codecov](https://codecov.io/gh/go-resty/resty/pull/621?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) Report
> Merging [#621](https://codecov.io/gh/go-resty/resty/pull/621?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) (c9ebcc9) into [master](https://codecov.io/gh/go-resty/resty/commit/9e2a9b71fb72d6d6f6a8828ef5a026c0f16d8ab8?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) (9e2a9b7) will **decrease** coverage by `0.85%`.
> The diff coverage is `0.00%`.

```diff
@@            Coverage Diff             @@
##           master     #621      +/-   ##
==========================================
- Coverage   95.94%   95.10%   -0.85%     
==========================================
  Files          10       10              
  Lines        1357     1369      +12     
==========================================
  Hits         1302     1302              
- Misses         34       46      +12     
  Partials       21       21              
```


| [Impacted Files](https://codecov.io/gh/go-resty/resty/pull/621?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty) | Coverage Δ | |
|---|---|---|
| [client.go](https://codecov.io/gh/go-resty/resty/pull/621?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty#diff-Y2xpZW50Lmdv) | `94.59% <0.00%> (-3.18%)` | :arrow_down: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=go-resty)

GRbit: @jeevatkm I'm glad that it makes you smile.

Sorry for taking your time on that, but could you please tell me what kind of tests should I do? The only test I can come up with is something like this:
```
func TestClientJSON(t *testing.T) {
	m := func (v interface{}) ([]byte, error) { return nil,nil }
	c := New().SetJSONMarshaler(m)
	assertEqual(t, m, c.JSONMarshal)
}
```
But it looks silly for me to test such things because I don't think this test could possibly be helpful.

If this is what you looking for – I'll be glad to add a test for each function. If not, please show me some examples in the code 
jeevatkm: @GRbit Thanks for the getting back. 

> @jeevatkm I'm glad that it makes you smile.
> 
> Sorry for taking your time on that ...

Just to be clear, why I mentioned about smile is regarding this part from the PR description. Because, time-to-time, I also do the same! 
> (let's be honest it's not only me who doesn't read docs)

----

I understand, what you mean. However, based on the PR context, we are introducing a new setter methods for populating certain field. So it make sense to add a tiny test case which calls those setter(s) and does the assertion.
GRbit: @jeevatkm I respect your standards, so my only question was "how should I make those tests?". Please check out the code I've just added, I hope it's ok.

Patch:
diff --git a/README.md b/README.md
index 8ec6518..64a859b 100644
--- a/README.md
+++ b/README.md
@@ -369,13 +369,13 @@ import jsoniter "github.com/json-iterator/go"
 
 json := jsoniter.ConfigCompatibleWithStandardLibrary
 
-client := resty.New()
-client.JSONMarshal = json.Marshal
-client.JSONUnmarshal = json.Unmarshal
+client := resty.New().
+    SetJSONMarshaler(json.Marshal).
+    SetJSONUnmarshaler(json.Unmarshal)
 
 // similarly user could do for XML too with -
-client.XMLMarshal
-client.XMLUnmarshal
+client.SetXMLMarshaler(xml.Marshal).
+    SetXMLUnmarshaler(xml.Unmarshal)
 ```
 
 ### Multipart File(s) upload
diff --git a/client.go b/client.go
index e65e3ce..af559f7 100644
--- a/client.go
+++ b/client.go
@@ -682,6 +682,34 @@ func (c *Client) SetRetryAfter(callback RetryAfterFunc) *Client {
 	return c
 }
 
+// SetJSONMarshaler method sets the JSON marshaler function to marshal the request body.
+// By default, Resty uses `encoding/json` package to marshal the request body.
+func (c *Client) SetJSONMarshaler(marshaler func(v interface{}) ([]byte, error)) *Client {
+	c.JSONMarshal = marshaler
+	return c
+}
+
+// SetJSONUnmarshaler method sets the JSON unmarshaler function to unmarshal the response body.
+// By default, Resty uses `encoding/json` package to unmarshal the response body.
+func (c *Client) SetJSONUnmarshaler(unmarshaler func(data []byte, v interface{}) error) *Client {
+	c.JSONUnmarshal = unmarshaler
+	return c
+}
+
+// SetXMLMarshaler method sets the XML marshaler function to marshal the request body.
+// By default, Resty uses `encoding/xml` package to marshal the request body.
+func (c *Client) SetXMLMarshaler(marshaler func(v interface{}) ([]byte, error)) *Client {
+	c.XMLMarshal = marshaler
+	return c
+}
+
+// SetXMLUnmarshaler method sets the XML unmarshaler function to unmarshal the response body.
+// By default, Resty uses `encoding/xml` package to unmarshal the response body.
+func (c *Client) SetXMLUnmarshaler(unmarshaler func(data []byte, v interface{}) error) *Client {
+	c.XMLUnmarshal = unmarshaler
+	return c
+}
+
 // AddRetryCondition method adds a retry condition function to array of functions
 // that are checked to determine if the request is retried. The request will
 // retry if any of the functions return true and error is nil.


Test patch:
diff --git a/client_test.go b/client_test.go
index b640747..fb45ced 100644
--- a/client_test.go
+++ b/client_test.go
@@ -509,6 +509,39 @@ func TestClientNewRequest(t *testing.T) {
 	assertNotNil(t, request)
 }
 
+
+func TestClientSetJSONMarshaler(t *testing.T) {
+	m := func (v interface{}) ([]byte, error) { return nil,nil }
+	c := New().SetJSONMarshaler(m)
+	p1 := fmt.Sprintf("%p", c.JSONMarshal)
+	p2 := fmt.Sprintf("%p", m)
+	assertEqual(t, p1, p2) // functions can not be compared, we only can compare pointers
+}
+
+func TestClientSetJSONUnmarshaler(t *testing.T) {
+	m := func ([]byte, interface{}) error { return nil }
+	c := New().SetJSONUnmarshaler(m)
+	p1 := fmt.Sprintf("%p", c.JSONUnmarshal)
+	p2 := fmt.Sprintf("%p", m)
+	assertEqual(t, p1, p2) // functions can not be compared, we only can compare pointers
+}
+
+func TestClientSetXMLMarshaler(t *testing.T) {
+	m := func (v interface{}) ([]byte, error) { return nil,nil }
+	c := New().SetXMLMarshaler(m)
+	p1 := fmt.Sprintf("%p", c.XMLMarshal)
+	p2 := fmt.Sprintf("%p", m)
+	assertEqual(t, p1, p2) // functions can not be compared, we only can compare pointers
+}
+
+func TestClientSetXMLUnmarshaler(t *testing.T) {
+	m := func ([]byte, interface{}) error { return nil }
+	c := New().SetXMLUnmarshaler(m)
+	p1 := fmt.Sprintf("%p", c.XMLUnmarshal)
+	p2 := fmt.Sprintf("%p", m)
+	assertEqual(t, p1, p2) // functions can not be compared, we only can compare pointers
+}
+
 func TestDebugBodySizeLimit(t *testing.T) {
 	ts := createGetServer(t)
 	defer ts.Close()