1
0
mirror of https://github.com/golang/go synced 2024-11-25 11:27:56 -07:00

encoding/json: escape output from Marshalers.

Fixes #3127.

R=rsc, r
CC=golang-dev
https://golang.org/cl/5707054
This commit is contained in:
David Symonds 2012-03-01 17:41:59 +11:00
parent ed238ca4e5
commit 99e45e49b7
3 changed files with 33 additions and 1 deletions

View File

@ -260,7 +260,7 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
b, err := m.MarshalJSON() b, err := m.MarshalJSON()
if err == nil { if err == nil {
// copy JSON into buffer, checking validity. // copy JSON into buffer, checking validity.
err = Compact(&e.Buffer, b) err = compact(&e.Buffer, b, true)
} }
if err != nil { if err != nil {
e.error(&MarshalerError{v.Type(), err}) e.error(&MarshalerError{v.Type(), err})

View File

@ -167,3 +167,22 @@ func TestRefValMarshal(t *testing.T) {
t.Errorf("got %q, want %q", got, want) t.Errorf("got %q, want %q", got, want)
} }
} }
// C implements Marshaler and returns unescaped JSON.
type C int
func (C) MarshalJSON() ([]byte, error) {
return []byte(`"<&>"`), nil
}
func TestMarshalerEscaping(t *testing.T) {
var c C
const want = `"\u003c\u0026\u003e"`
b, err := Marshal(c)
if err != nil {
t.Fatalf("Marshal: %v", err)
}
if got := string(b); got != want {
t.Errorf("got %q, want %q", got, want)
}
}

View File

@ -9,11 +9,24 @@ import "bytes"
// Compact appends to dst the JSON-encoded src with // Compact appends to dst the JSON-encoded src with
// insignificant space characters elided. // insignificant space characters elided.
func Compact(dst *bytes.Buffer, src []byte) error { func Compact(dst *bytes.Buffer, src []byte) error {
return compact(dst, src, false)
}
func compact(dst *bytes.Buffer, src []byte, escape bool) error {
origLen := dst.Len() origLen := dst.Len()
var scan scanner var scan scanner
scan.reset() scan.reset()
start := 0 start := 0
for i, c := range src { for i, c := range src {
if escape && (c == '<' || c == '>' || c == '&') {
if start < i {
dst.Write(src[start:i])
}
dst.WriteString(`\u00`)
dst.WriteByte(hex[c>>4])
dst.WriteByte(hex[c&0xF])
start = i + 1
}
v := scan.step(&scan, int(c)) v := scan.step(&scan, int(c))
if v >= scanSkipSpace { if v >= scanSkipSpace {
if v == scanError { if v == scanError {