Skip to content

Commit 62145fa

Browse files
im-kulikovvishr
authored andcommitted
[extend #1191] Unnecessary alloc for XML, JSON, JSONP (#1199)
* [extend #1191] Unnecessary alloc for XML, JSON, JSONP * add legacy (JSON/JSONP/XML)Blob tests * fix namings * fix `jsonPBlob` allocs * fix review comments (thx @alexaandru) * fix review comments (thx @alexaandru) add benchmarks
1 parent e6ac002 commit 62145fa

2 files changed

Lines changed: 207 additions & 56 deletions

File tree

context.go

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ const (
206206
indexPage = "index.html"
207207
)
208208

209+
var defaultIndent = " "
210+
209211
func (c *context) writeContentType(value string) {
210212
header := c.Response().Header()
211213
if header.Get(HeaderContentType) == "" {
@@ -403,36 +405,54 @@ func (c *context) String(code int, s string) (err error) {
403405
return c.Blob(code, MIMETextPlainCharsetUTF8, []byte(s))
404406
}
405407

406-
func (c *context) JSON(code int, i interface{}) (err error) {
408+
func (c *context) jsonPBlob(code int, callback string, i interface{}) (err error) {
409+
enc := json.NewEncoder(c.response)
407410
_, pretty := c.QueryParams()["pretty"]
408411
if c.echo.Debug || pretty {
409-
return c.JSONPretty(code, i, " ")
412+
enc.SetIndent("", " ")
410413
}
411-
b, err := json.Marshal(i)
412-
if err != nil {
414+
c.writeContentType(MIMEApplicationJavaScriptCharsetUTF8)
415+
c.response.WriteHeader(code)
416+
if _, err = c.response.Write([]byte(callback + "(")); err != nil {
417+
return
418+
}
419+
if err = enc.Encode(i); err != nil {
420+
return
421+
}
422+
if _, err = c.response.Write([]byte(");")); err != nil {
413423
return
414424
}
415-
return c.JSONBlob(code, b)
425+
return
416426
}
417427

418-
func (c *context) JSONPretty(code int, i interface{}, indent string) (err error) {
419-
b, err := json.MarshalIndent(i, "", indent)
420-
if err != nil {
421-
return
428+
func (c *context) jsonBlob(code int, i interface{}, indent *string) error {
429+
enc := json.NewEncoder(c.response)
430+
if indent != nil {
431+
enc.SetIndent("", *indent)
432+
}
433+
c.writeContentType(MIMEApplicationJSONCharsetUTF8)
434+
c.response.WriteHeader(code)
435+
return enc.Encode(i)
436+
}
437+
438+
func (c *context) JSON(code int, i interface{}) (err error) {
439+
var indent *string
440+
if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
441+
indent = &defaultIndent
422442
}
423-
return c.JSONBlob(code, b)
443+
return c.jsonBlob(code, i, indent)
444+
}
445+
446+
func (c *context) JSONPretty(code int, i interface{}, indent string) (err error) {
447+
return c.jsonBlob(code, i, &indent)
424448
}
425449

426450
func (c *context) JSONBlob(code int, b []byte) (err error) {
427451
return c.Blob(code, MIMEApplicationJSONCharsetUTF8, b)
428452
}
429453

430454
func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
431-
b, err := json.Marshal(i)
432-
if err != nil {
433-
return
434-
}
435-
return c.JSONPBlob(code, callback, b)
455+
return c.jsonPBlob(code, callback, i)
436456
}
437457

438458
func (c *context) JSONPBlob(code int, callback string, b []byte) (err error) {
@@ -448,24 +468,29 @@ func (c *context) JSONPBlob(code int, callback string, b []byte) (err error) {
448468
return
449469
}
450470

451-
func (c *context) XML(code int, i interface{}) (err error) {
452-
_, pretty := c.QueryParams()["pretty"]
453-
if c.echo.Debug || pretty {
454-
return c.XMLPretty(code, i, " ")
471+
func (c *context) xmlBlob(code int, i interface{}, indent *string) (err error) {
472+
c.writeContentType(MIMEApplicationXMLCharsetUTF8)
473+
c.response.WriteHeader(code)
474+
enc := xml.NewEncoder(c.response)
475+
if indent != nil {
476+
enc.Indent("", *indent)
455477
}
456-
b, err := xml.Marshal(i)
457-
if err != nil {
478+
if _, err = c.response.Write([]byte(xml.Header)); err != nil {
458479
return
459480
}
460-
return c.XMLBlob(code, b)
481+
return enc.Encode(i)
461482
}
462483

463-
func (c *context) XMLPretty(code int, i interface{}, indent string) (err error) {
464-
b, err := xml.MarshalIndent(i, "", indent)
465-
if err != nil {
466-
return
484+
func (c *context) XML(code int, i interface{}) (err error) {
485+
var indent *string
486+
if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
487+
indent = &defaultIndent
467488
}
468-
return c.XMLBlob(code, b)
489+
return c.xmlBlob(code, i, indent)
490+
}
491+
492+
func (c *context) XMLPretty(code int, i interface{}, indent string) (err error) {
493+
return c.xmlBlob(code, i, &indent)
469494
}
470495

471496
func (c *context) XMLBlob(code int, b []byte) (err error) {

0 commit comments

Comments
 (0)