How to stop json.Marshal from escaping < and >?

As of Go 1.7, you still cannot do this with json.Marshal(). The source code for json.Marshal shows:

> err := e.marshal(v, encOpts{escapeHTML: true})

The reason json.Marshal always does this is:

String values encode as JSON strings coerced to valid UTF-8,
replacing invalid bytes with the Unicode replacement rune.
The angle brackets “<” and “>” are escaped to “\u003c” and “\u003e”
to keep some browsers from misinterpreting JSON output as HTML.
Ampersand “&” is also escaped to “\u0026” for the same reason.

This means you cannot even do it by writing a custom func (t *Track) MarshalJSON(), you have to use something that does not satisfy the json.Marshaler interface.

So, the workaround, is to write your own function:

func (t *Track) JSON() ([]byte, error) {
    buffer := &bytes.Buffer{}
    encoder := json.NewEncoder(buffer)
    encoder.SetEscapeHTML(false)
    err := encoder.Encode(t)
    return buffer.Bytes(), err
}

https://play.golang.org/p/FAH-XS-QMC

If you want a generic solution for any struct, you could do:

func JSONMarshal(t interface{}) ([]byte, error) {
    buffer := &bytes.Buffer{}
    encoder := json.NewEncoder(buffer)
    encoder.SetEscapeHTML(false)
    err := encoder.Encode(t)
    return buffer.Bytes(), err
}

https://play.golang.org/p/bdqv3TUGr3

Leave a Comment