1package json
2
3import (
4	"bytes"
5	"encoding/json"
6	"io"
7	"math/bits"
8	"reflect"
9	"runtime"
10	"sync"
11	"unsafe"
12)
13
14// Delim is documented at https://golang.org/pkg/encoding/json/#Delim
15type Delim = json.Delim
16
17// InvalidUTF8Error is documented at https://golang.org/pkg/encoding/json/#InvalidUTF8Error
18type InvalidUTF8Error = json.InvalidUTF8Error
19
20// InvalidUnmarshalError is documented at https://golang.org/pkg/encoding/json/#InvalidUnmarshalError
21type InvalidUnmarshalError = json.InvalidUnmarshalError
22
23// Marshaler is documented at https://golang.org/pkg/encoding/json/#Marshaler
24type Marshaler = json.Marshaler
25
26// MarshalerError is documented at https://golang.org/pkg/encoding/json/#MarshalerError
27type MarshalerError = json.MarshalerError
28
29// Number is documented at https://golang.org/pkg/encoding/json/#Number
30type Number = json.Number
31
32// RawMessage is documented at https://golang.org/pkg/encoding/json/#RawMessage
33type RawMessage = json.RawMessage
34
35// A SyntaxError is a description of a JSON syntax error.
36type SyntaxError = json.SyntaxError
37
38// Token is documented at https://golang.org/pkg/encoding/json/#Token
39type Token = json.Token
40
41// UnmarshalFieldError is documented at https://golang.org/pkg/encoding/json/#UnmarshalFieldError
42type UnmarshalFieldError = json.UnmarshalFieldError
43
44// UnmarshalTypeError is documented at https://golang.org/pkg/encoding/json/#UnmarshalTypeError
45type UnmarshalTypeError = json.UnmarshalTypeError
46
47// Unmarshaler is documented at https://golang.org/pkg/encoding/json/#Unmarshaler
48type Unmarshaler = json.Unmarshaler
49
50// UnsupportedTypeError is documented at https://golang.org/pkg/encoding/json/#UnsupportedTypeError
51type UnsupportedTypeError = json.UnsupportedTypeError
52
53// UnsupportedValueError is documented at https://golang.org/pkg/encoding/json/#UnsupportedValueError
54type UnsupportedValueError = json.UnsupportedValueError
55
56// AppendFlags is a type used to represent configuration options that can be
57// applied when formatting json output.
58type AppendFlags uint
59
60const (
61	// EscapeHTML is a formatting flag used to to escape HTML in json strings.
62	EscapeHTML AppendFlags = 1 << iota
63
64	// SortMapKeys is formatting flag used to enable sorting of map keys when
65	// encoding JSON (this matches the behavior of the standard encoding/json
66	// package).
67	SortMapKeys
68
69	// TrustRawMessage is a performance optimization flag to skip value
70	// checking of raw messages. It should only be used if the values are
71	// known to be valid json (e.g., they were created by json.Unmarshal).
72	TrustRawMessage
73)
74
75// ParseFlags is a type used to represent configuration options that can be
76// applied when parsing json input.
77type ParseFlags uint
78
79func (flags ParseFlags) has(f ParseFlags) bool {
80	return (flags & f) != 0
81}
82
83func (f ParseFlags) kind() Kind {
84	return Kind((f >> kindOffset) & 0xFF)
85}
86
87func (f ParseFlags) withKind(kind Kind) ParseFlags {
88	return (f & ^(ParseFlags(0xFF) << kindOffset)) | (ParseFlags(kind) << kindOffset)
89}
90
91const (
92	// DisallowUnknownFields is a parsing flag used to prevent decoding of
93	// objects to Go struct values when a field of the input does not match
94	// with any of the struct fields.
95	DisallowUnknownFields ParseFlags = 1 << iota
96
97	// UseNumber is a parsing flag used to load numeric values as Number
98	// instead of float64.
99	UseNumber
100
101	// DontCopyString is a parsing flag used to provide zero-copy support when
102	// loading string values from a json payload. It is not always possible to
103	// avoid dynamic memory allocations, for example when a string is escaped in
104	// the json data a new buffer has to be allocated, but when the `wire` value
105	// can be used as content of a Go value the decoder will simply point into
106	// the input buffer.
107	DontCopyString
108
109	// DontCopyNumber is a parsing flag used to provide zero-copy support when
110	// loading Number values (see DontCopyString and DontCopyRawMessage).
111	DontCopyNumber
112
113	// DontCopyRawMessage is a parsing flag used to provide zero-copy support
114	// when loading RawMessage values from a json payload. When used, the
115	// RawMessage values will not be allocated into new memory buffers and
116	// will instead point directly to the area of the input buffer where the
117	// value was found.
118	DontCopyRawMessage
119
120	// DontMatchCaseInsensitiveStructFields is a parsing flag used to prevent
121	// matching fields in a case-insensitive way. This can prevent degrading
122	// performance on case conversions, and can also act as a stricter decoding
123	// mode.
124	DontMatchCaseInsensitiveStructFields
125
126	// ZeroCopy is a parsing flag that combines all the copy optimizations
127	// available in the package.
128	//
129	// The zero-copy optimizations are better used in request-handler style
130	// code where none of the values are retained after the handler returns.
131	ZeroCopy = DontCopyString | DontCopyNumber | DontCopyRawMessage
132
133	// validAsciiPrint is an internal flag indicating that the input contains
134	// only valid ASCII print chars (0x20 <= c <= 0x7E). If the flag is unset,
135	// it's unknown whether the input is valid ASCII print.
136	validAsciiPrint ParseFlags = 1 << 28
137
138	// noBackslach is an internal flag indicating that the input does not
139	// contain a backslash. If the flag is unset, it's unknown whether the
140	// input contains a backslash.
141	noBackslash ParseFlags = 1 << 29
142
143	// Bit offset where the kind of the json value is stored.
144	//
145	// See Kind in token.go for the enum.
146	kindOffset ParseFlags = 16
147)
148
149// Kind represents the different kinds of value that exist in JSON.
150type Kind uint
151
152const (
153	Undefined Kind = 0
154
155	Null Kind = 1 // Null is not zero, so we keep zero for "undefined".
156
157	Bool  Kind = 2 // Bit two is set to 1, means it's a boolean.
158	False Kind = 2 // Bool + 0
159	True  Kind = 3 // Bool + 1
160
161	Num   Kind = 4 // Bit three is set to 1, means it's a number.
162	Uint  Kind = 5 // Num + 1
163	Int   Kind = 6 // Num + 2
164	Float Kind = 7 // Num + 3
165
166	String    Kind = 8 // Bit four is set to 1, means it's a string.
167	Unescaped Kind = 9 // String + 1
168
169	Array  Kind = 16 // Equivalent to Delim == '['
170	Object Kind = 32 // Equivalent to Delim == '{'
171)
172
173// Class returns the class of k.
174func (k Kind) Class() Kind { return Kind(1 << uint(bits.Len(uint(k))-1)) }
175
176// Append acts like Marshal but appends the json representation to b instead of
177// always reallocating a new slice.
178func Append(b []byte, x interface{}, flags AppendFlags) ([]byte, error) {
179	if x == nil {
180		// Special case for nil values because it makes the rest of the code
181		// simpler to assume that it won't be seeing nil pointers.
182		return append(b, "null"...), nil
183	}
184
185	t := reflect.TypeOf(x)
186	p := (*iface)(unsafe.Pointer(&x)).ptr
187
188	cache := cacheLoad()
189	c, found := cache[typeid(t)]
190
191	if !found {
192		c = constructCachedCodec(t, cache)
193	}
194
195	b, err := c.encode(encoder{flags: flags}, b, p)
196	runtime.KeepAlive(x)
197	return b, err
198}
199
200// Escape is a convenience helper to construct an escaped JSON string from s.
201// The function escales HTML characters, for more control over the escape
202// behavior and to write to a pre-allocated buffer, use AppendEscape.
203func Escape(s string) []byte {
204	// +10 for extra escape characters, maybe not enough and the buffer will
205	// be reallocated.
206	b := make([]byte, 0, len(s)+10)
207	return AppendEscape(b, s, EscapeHTML)
208}
209
210// AppendEscape appends s to b with the string escaped as a JSON value.
211// This will include the starting and ending quote characters, and the
212// appropriate characters will be escaped correctly for JSON encoding.
213func AppendEscape(b []byte, s string, flags AppendFlags) []byte {
214	e := encoder{flags: flags}
215	b, _ = e.encodeString(b, unsafe.Pointer(&s))
216	return b
217}
218
219// Unescape is a convenience helper to unescape a JSON value.
220// For more control over the unescape behavior and
221// to write to a pre-allocated buffer, use AppendUnescape.
222func Unescape(s []byte) []byte {
223	b := make([]byte, 0, len(s))
224	return AppendUnescape(b, s, ParseFlags(0))
225}
226
227// AppendUnescape appends s to b with the string unescaped as a JSON value.
228// This will remove starting and ending quote characters, and the
229// appropriate characters will be escaped correctly as if JSON decoded.
230// New space will be reallocated if more space is needed.
231func AppendUnescape(b []byte, s []byte, flags ParseFlags) []byte {
232	d := decoder{flags: flags}
233	buf := new(string)
234	d.decodeString(s, unsafe.Pointer(buf))
235	return append(b, *buf...)
236}
237
238// Compact is documented at https://golang.org/pkg/encoding/json/#Compact
239func Compact(dst *bytes.Buffer, src []byte) error {
240	return json.Compact(dst, src)
241}
242
243// HTMLEscape is documented at https://golang.org/pkg/encoding/json/#HTMLEscape
244func HTMLEscape(dst *bytes.Buffer, src []byte) {
245	json.HTMLEscape(dst, src)
246}
247
248// Indent is documented at https://golang.org/pkg/encoding/json/#Indent
249func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
250	return json.Indent(dst, src, prefix, indent)
251}
252
253// Marshal is documented at https://golang.org/pkg/encoding/json/#Marshal
254func Marshal(x interface{}) ([]byte, error) {
255	var err error
256	var buf = encoderBufferPool.Get().(*encoderBuffer)
257
258	if buf.data, err = Append(buf.data[:0], x, EscapeHTML|SortMapKeys); err != nil {
259		return nil, err
260	}
261
262	b := make([]byte, len(buf.data))
263	copy(b, buf.data)
264	encoderBufferPool.Put(buf)
265	return b, nil
266}
267
268// MarshalIndent is documented at https://golang.org/pkg/encoding/json/#MarshalIndent
269func MarshalIndent(x interface{}, prefix, indent string) ([]byte, error) {
270	b, err := Marshal(x)
271
272	if err == nil {
273		tmp := &bytes.Buffer{}
274		tmp.Grow(2 * len(b))
275
276		Indent(tmp, b, prefix, indent)
277		b = tmp.Bytes()
278	}
279
280	return b, err
281}
282
283// Unmarshal is documented at https://golang.org/pkg/encoding/json/#Unmarshal
284func Unmarshal(b []byte, x interface{}) error {
285	r, err := Parse(b, x, 0)
286	if len(r) != 0 {
287		if _, ok := err.(*SyntaxError); !ok {
288			// The encoding/json package prioritizes reporting errors caused by
289			// unexpected trailing bytes over other issues; here we emulate this
290			// behavior by overriding the error.
291			err = syntaxError(r, "invalid character '%c' after top-level value", r[0])
292		}
293	}
294	return err
295}
296
297// Parse behaves like Unmarshal but the caller can pass a set of flags to
298// configure the parsing behavior.
299func Parse(b []byte, x interface{}, flags ParseFlags) ([]byte, error) {
300	t := reflect.TypeOf(x)
301	p := (*iface)(unsafe.Pointer(&x)).ptr
302
303	d := decoder{flags: flags | internalParseFlags(b)}
304
305	b = skipSpaces(b)
306
307	if t == nil || p == nil || t.Kind() != reflect.Ptr {
308		_, r, _, err := d.parseValue(b)
309		r = skipSpaces(r)
310		if err != nil {
311			return r, err
312		}
313		return r, &InvalidUnmarshalError{Type: t}
314	}
315	t = t.Elem()
316
317	cache := cacheLoad()
318	c, found := cache[typeid(t)]
319
320	if !found {
321		c = constructCachedCodec(t, cache)
322	}
323
324	r, err := c.decode(d, b, p)
325	return skipSpaces(r), err
326}
327
328// Valid is documented at https://golang.org/pkg/encoding/json/#Valid
329func Valid(data []byte) bool {
330	data = skipSpaces(data)
331	d := decoder{flags: internalParseFlags(data)}
332	_, data, _, err := d.parseValue(data)
333	if err != nil {
334		return false
335	}
336	return len(skipSpaces(data)) == 0
337}
338
339// Decoder is documented at https://golang.org/pkg/encoding/json/#Decoder
340type Decoder struct {
341	reader      io.Reader
342	buffer      []byte
343	remain      []byte
344	inputOffset int64
345	err         error
346	flags       ParseFlags
347}
348
349// NewDecoder is documented at https://golang.org/pkg/encoding/json/#NewDecoder
350func NewDecoder(r io.Reader) *Decoder { return &Decoder{reader: r} }
351
352// Buffered is documented at https://golang.org/pkg/encoding/json/#Decoder.Buffered
353func (dec *Decoder) Buffered() io.Reader {
354	return bytes.NewReader(dec.remain)
355}
356
357// Decode is documented at https://golang.org/pkg/encoding/json/#Decoder.Decode
358func (dec *Decoder) Decode(v interface{}) error {
359	raw, err := dec.readValue()
360	if err != nil {
361		return err
362	}
363	_, err = Parse(raw, v, dec.flags)
364	return err
365}
366
367const (
368	minBufferSize = 32768
369	minReadSize   = 4096
370)
371
372// readValue reads one JSON value from the buffer and returns its raw bytes. It
373// is optimized for the "one JSON value per line" case.
374func (dec *Decoder) readValue() (v []byte, err error) {
375	var n int
376	var r []byte
377	d := decoder{flags: dec.flags}
378
379	for {
380		if len(dec.remain) != 0 {
381			v, r, _, err = d.parseValue(dec.remain)
382			if err == nil {
383				dec.remain, n = skipSpacesN(r)
384				dec.inputOffset += int64(len(v) + n)
385				return
386			}
387			if len(r) != 0 {
388				// Parsing of the next JSON value stopped at a position other
389				// than the end of the input buffer, which indicaates that a
390				// syntax error was encountered.
391				return
392			}
393		}
394
395		if err = dec.err; err != nil {
396			if len(dec.remain) != 0 && err == io.EOF {
397				err = io.ErrUnexpectedEOF
398			}
399			return
400		}
401
402		if dec.buffer == nil {
403			dec.buffer = make([]byte, 0, minBufferSize)
404		} else {
405			dec.buffer = dec.buffer[:copy(dec.buffer[:cap(dec.buffer)], dec.remain)]
406			dec.remain = nil
407		}
408
409		if (cap(dec.buffer) - len(dec.buffer)) < minReadSize {
410			buf := make([]byte, len(dec.buffer), 2*cap(dec.buffer))
411			copy(buf, dec.buffer)
412			dec.buffer = buf
413		}
414
415		n, err = io.ReadFull(dec.reader, dec.buffer[len(dec.buffer):cap(dec.buffer)])
416		if n > 0 {
417			dec.buffer = dec.buffer[:len(dec.buffer)+n]
418			if err != nil {
419				err = nil
420			}
421		} else if err == io.ErrUnexpectedEOF {
422			err = io.EOF
423		}
424		dec.remain, n = skipSpacesN(dec.buffer)
425		d.flags = dec.flags | internalParseFlags(dec.remain)
426		dec.inputOffset += int64(n)
427		dec.err = err
428	}
429}
430
431// DisallowUnknownFields is documented at https://golang.org/pkg/encoding/json/#Decoder.DisallowUnknownFields
432func (dec *Decoder) DisallowUnknownFields() { dec.flags |= DisallowUnknownFields }
433
434// UseNumber is documented at https://golang.org/pkg/encoding/json/#Decoder.UseNumber
435func (dec *Decoder) UseNumber() { dec.flags |= UseNumber }
436
437// DontCopyString is an extension to the standard encoding/json package
438// which instructs the decoder to not copy strings loaded from the json
439// payloads when possible.
440func (dec *Decoder) DontCopyString() { dec.flags |= DontCopyString }
441
442// DontCopyNumber is an extension to the standard encoding/json package
443// which instructs the decoder to not copy numbers loaded from the json
444// payloads.
445func (dec *Decoder) DontCopyNumber() { dec.flags |= DontCopyNumber }
446
447// DontCopyRawMessage is an extension to the standard encoding/json package
448// which instructs the decoder to not allocate RawMessage values in separate
449// memory buffers (see the documentation of the DontcopyRawMessage flag for
450// more detais).
451func (dec *Decoder) DontCopyRawMessage() { dec.flags |= DontCopyRawMessage }
452
453// DontMatchCaseInsensitiveStructFields is an extension to the standard
454// encoding/json package which instructs the decoder to not match object fields
455// against struct fields in a case-insensitive way, the field names have to
456// match exactly to be decoded into the struct field values.
457func (dec *Decoder) DontMatchCaseInsensitiveStructFields() {
458	dec.flags |= DontMatchCaseInsensitiveStructFields
459}
460
461// ZeroCopy is an extension to the standard encoding/json package which enables
462// all the copy optimizations of the decoder.
463func (dec *Decoder) ZeroCopy() { dec.flags |= ZeroCopy }
464
465// InputOffset returns the input stream byte offset of the current decoder position.
466// The offset gives the location of the end of the most recently returned token
467// and the beginning of the next token.
468func (dec *Decoder) InputOffset() int64 {
469	return dec.inputOffset
470}
471
472// Encoder is documented at https://golang.org/pkg/encoding/json/#Encoder
473type Encoder struct {
474	writer io.Writer
475	prefix string
476	indent string
477	buffer *bytes.Buffer
478	err    error
479	flags  AppendFlags
480}
481
482// NewEncoder is documented at https://golang.org/pkg/encoding/json/#NewEncoder
483func NewEncoder(w io.Writer) *Encoder { return &Encoder{writer: w, flags: EscapeHTML | SortMapKeys} }
484
485// Encode is documented at https://golang.org/pkg/encoding/json/#Encoder.Encode
486func (enc *Encoder) Encode(v interface{}) error {
487	if enc.err != nil {
488		return enc.err
489	}
490
491	var err error
492	var buf = encoderBufferPool.Get().(*encoderBuffer)
493
494	buf.data, err = Append(buf.data[:0], v, enc.flags)
495
496	if err != nil {
497		encoderBufferPool.Put(buf)
498		return err
499	}
500
501	buf.data = append(buf.data, '\n')
502	b := buf.data
503
504	if enc.prefix != "" || enc.indent != "" {
505		if enc.buffer == nil {
506			enc.buffer = new(bytes.Buffer)
507			enc.buffer.Grow(2 * len(buf.data))
508		} else {
509			enc.buffer.Reset()
510		}
511		Indent(enc.buffer, buf.data, enc.prefix, enc.indent)
512		b = enc.buffer.Bytes()
513	}
514
515	if _, err := enc.writer.Write(b); err != nil {
516		enc.err = err
517	}
518
519	encoderBufferPool.Put(buf)
520	return err
521}
522
523// SetEscapeHTML is documented at https://golang.org/pkg/encoding/json/#Encoder.SetEscapeHTML
524func (enc *Encoder) SetEscapeHTML(on bool) {
525	if on {
526		enc.flags |= EscapeHTML
527	} else {
528		enc.flags &= ^EscapeHTML
529	}
530}
531
532// SetIndent is documented at https://golang.org/pkg/encoding/json/#Encoder.SetIndent
533func (enc *Encoder) SetIndent(prefix, indent string) {
534	enc.prefix = prefix
535	enc.indent = indent
536}
537
538// SetSortMapKeys is an extension to the standard encoding/json package which
539// allows the program to toggle sorting of map keys on and off.
540func (enc *Encoder) SetSortMapKeys(on bool) {
541	if on {
542		enc.flags |= SortMapKeys
543	} else {
544		enc.flags &= ^SortMapKeys
545	}
546}
547
548// SetTrustRawMessage skips value checking when encoding a raw json message. It should only
549// be used if the values are known to be valid json, e.g. because they were originally created
550// by json.Unmarshal.
551func (enc *Encoder) SetTrustRawMessage(on bool) {
552	if on {
553		enc.flags |= TrustRawMessage
554	} else {
555		enc.flags &= ^TrustRawMessage
556	}
557}
558
559var encoderBufferPool = sync.Pool{
560	New: func() interface{} { return &encoderBuffer{data: make([]byte, 0, 4096)} },
561}
562
563type encoderBuffer struct{ data []byte }
564