From 09c4cb6dd8f91d152041a8bf4c29f6eeb56af5ce Mon Sep 17 00:00:00 2001 From: qingyu31 Date: Sun, 3 Nov 2019 15:17:32 +0800 Subject: [PATCH] add trustMarshaler option to JSON encoder aimed at improving precomputed performance. --- src/encoding/json/encode.go | 18 ++++++++++++++---- src/encoding/json/stream.go | 18 ++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index b81e5058660f73..848f84bd185ee7 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -349,6 +349,8 @@ type encOpts struct { quoted bool // escapeHTML causes '<', '>', and '&' to be escaped in JSON strings. escapeHTML bool + // trustMarshaler causes Marshaler not to be compacted, escaped and validated. + trustMarshaler bool } type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts) @@ -462,8 +464,12 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { } b, err := m.MarshalJSON() if err == nil { - // copy JSON into buffer, checking validity. - err = compact(&e.Buffer, b, opts.escapeHTML) + // copy JSON in to buffer. + if opts.trustMarshaler { + _, err = e.Buffer.Write(b) + } else { + err = compact(&e.Buffer, b, opts.escapeHTML) + } } if err != nil { e.error(&MarshalerError{v.Type(), err, "MarshalJSON"}) @@ -479,8 +485,12 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) { m := va.Interface().(Marshaler) b, err := m.MarshalJSON() if err == nil { - // copy JSON into buffer, checking validity. - err = compact(&e.Buffer, b, opts.escapeHTML) + // copy JSON in to buffer. + if opts.trustMarshaler { + _, err = e.Buffer.Write(b) + } else { + err = compact(&e.Buffer, b, opts.escapeHTML) + } } if err != nil { e.error(&MarshalerError{v.Type(), err, "MarshalJSON"}) diff --git a/src/encoding/json/stream.go b/src/encoding/json/stream.go index 81f404f4267d08..9a50963ae983e2 100644 --- a/src/encoding/json/stream.go +++ b/src/encoding/json/stream.go @@ -179,9 +179,10 @@ func nonSpace(b []byte) bool { // An Encoder writes JSON values to an output stream. type Encoder struct { - w io.Writer - err error - escapeHTML bool + w io.Writer + err error + escapeHTML bool + trustMarshaler bool indentBuf *bytes.Buffer indentPrefix string @@ -203,7 +204,7 @@ func (enc *Encoder) Encode(v interface{}) error { return enc.err } e := newEncodeState() - err := e.marshal(v, encOpts{escapeHTML: enc.escapeHTML}) + err := e.marshal(v, encOpts{escapeHTML: enc.escapeHTML, trustMarshaler: enc.trustMarshaler}) if err != nil { return err } @@ -254,6 +255,15 @@ func (enc *Encoder) SetEscapeHTML(on bool) { enc.escapeHTML = on } +// SetTrustMarshaler specifies whether fields implement Marshaler +// should be computed such as escape, compact. +// The default behavior is to run compact on output of Marshaler. +// SetTrustMarshaler(true) just copies output of Marshaler +// and makes better performance. +func (enc *Encoder) SetTrustMarshaler(on bool) { + enc.trustMarshaler = on +} + // RawMessage is a raw encoded JSON value. // It implements Marshaler and Unmarshaler and can // be used to delay JSON decoding or precompute a JSON encoding.