1// Copyright 2010 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package json implements encoding and decoding of JSON as defined in
6// RFC 7159. The mapping between JSON and Go values is described
7// in the documentation for the Marshal and Unmarshal functions.
8//
9// See "JSON and Go" for an introduction to this package:
10// https://golang.org/doc/articles/json_and_go.html
11package json
12
13import (
14	"bytes"
15	"cmp"
16	"encoding"
17	"encoding/base64"
18	"fmt"
19	"math"
20	"reflect"
21	"slices"
22	"strconv"
23	"strings"
24	"sync"
25	"unicode"
26	"unicode/utf8"
27	_ "unsafe" // for linkname
28)
29
30// Marshal returns the JSON encoding of v.
31//
32// Marshal traverses the value v recursively.
33// If an encountered value implements [Marshaler]
34// and is not a nil pointer, Marshal calls [Marshaler.MarshalJSON]
35// to produce JSON. If no [Marshaler.MarshalJSON] method is present but the
36// value implements [encoding.TextMarshaler] instead, Marshal calls
37// [encoding.TextMarshaler.MarshalText] and encodes the result as a JSON string.
38// The nil pointer exception is not strictly necessary
39// but mimics a similar, necessary exception in the behavior of
40// [Unmarshaler.UnmarshalJSON].
41//
42// Otherwise, Marshal uses the following type-dependent default encodings:
43//
44// Boolean values encode as JSON booleans.
45//
46// Floating point, integer, and [Number] values encode as JSON numbers.
47// NaN and +/-Inf values will return an [UnsupportedValueError].
48//
49// String values encode as JSON strings coerced to valid UTF-8,
50// replacing invalid bytes with the Unicode replacement rune.
51// So that the JSON will be safe to embed inside HTML <script> tags,
52// the string is encoded using [HTMLEscape],
53// which replaces "<", ">", "&", U+2028, and U+2029 are escaped
54// to "\u003c","\u003e", "\u0026", "\u2028", and "\u2029".
55// This replacement can be disabled when using an [Encoder],
56// by calling [Encoder.SetEscapeHTML](false).
57//
58// Array and slice values encode as JSON arrays, except that
59// []byte encodes as a base64-encoded string, and a nil slice
60// encodes as the null JSON value.
61//
62// Struct values encode as JSON objects.
63// Each exported struct field becomes a member of the object, using the
64// field name as the object key, unless the field is omitted for one of the
65// reasons given below.
66//
67// The encoding of each struct field can be customized by the format string
68// stored under the "json" key in the struct field's tag.
69// The format string gives the name of the field, possibly followed by a
70// comma-separated list of options. The name may be empty in order to
71// specify options without overriding the default field name.
72//
73// The "omitempty" option specifies that the field should be omitted
74// from the encoding if the field has an empty value, defined as
75// false, 0, a nil pointer, a nil interface value, and any empty array,
76// slice, map, or string.
77//
78// As a special case, if the field tag is "-", the field is always omitted.
79// Note that a field with name "-" can still be generated using the tag "-,".
80//
81// Examples of struct field tags and their meanings:
82//
83//	// Field appears in JSON as key "myName".
84//	Field int `json:"myName"`
85//
86//	// Field appears in JSON as key "myName" and
87//	// the field is omitted from the object if its value is empty,
88//	// as defined above.
89//	Field int `json:"myName,omitempty"`
90//
91//	// Field appears in JSON as key "Field" (the default), but
92//	// the field is skipped if empty.
93//	// Note the leading comma.
94//	Field int `json:",omitempty"`
95//
96//	// Field is ignored by this package.
97//	Field int `json:"-"`
98//
99//	// Field appears in JSON as key "-".
100//	Field int `json:"-,"`
101//
102// The "string" option signals that a field is stored as JSON inside a
103// JSON-encoded string. It applies only to fields of string, floating point,
104// integer, or boolean types. This extra level of encoding is sometimes used
105// when communicating with JavaScript programs:
106//
107//	Int64String int64 `json:",string"`
108//
109// The key name will be used if it's a non-empty string consisting of
110// only Unicode letters, digits, and ASCII punctuation except quotation
111// marks, backslash, and comma.
112//
113// Embedded struct fields are usually marshaled as if their inner exported fields
114// were fields in the outer struct, subject to the usual Go visibility rules amended
115// as described in the next paragraph.
116// An anonymous struct field with a name given in its JSON tag is treated as
117// having that name, rather than being anonymous.
118// An anonymous struct field of interface type is treated the same as having
119// that type as its name, rather than being anonymous.
120//
121// The Go visibility rules for struct fields are amended for JSON when
122// deciding which field to marshal or unmarshal. If there are
123// multiple fields at the same level, and that level is the least
124// nested (and would therefore be the nesting level selected by the
125// usual Go rules), the following extra rules apply:
126//
127// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
128// even if there are multiple untagged fields that would otherwise conflict.
129//
130// 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
131//
132// 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
133//
134// Handling of anonymous struct fields is new in Go 1.1.
135// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
136// an anonymous struct field in both current and earlier versions, give the field
137// a JSON tag of "-".
138//
139// Map values encode as JSON objects. The map's key type must either be a
140// string, an integer type, or implement [encoding.TextMarshaler]. The map keys
141// are sorted and used as JSON object keys by applying the following rules,
142// subject to the UTF-8 coercion described for string values above:
143//   - keys of any string type are used directly
144//   - keys that implement [encoding.TextMarshaler] are marshaled
145//   - integer keys are converted to strings
146//
147// Pointer values encode as the value pointed to.
148// A nil pointer encodes as the null JSON value.
149//
150// Interface values encode as the value contained in the interface.
151// A nil interface value encodes as the null JSON value.
152//
153// Channel, complex, and function values cannot be encoded in JSON.
154// Attempting to encode such a value causes Marshal to return
155// an [UnsupportedTypeError].
156//
157// JSON cannot represent cyclic data structures and Marshal does not
158// handle them. Passing cyclic structures to Marshal will result in
159// an error.
160func Marshal(v any) ([]byte, error) {
161	e := newEncodeState()
162	defer encodeStatePool.Put(e)
163
164	err := e.marshal(v, encOpts{escapeHTML: true})
165	if err != nil {
166		return nil, err
167	}
168	buf := append([]byte(nil), e.Bytes()...)
169
170	return buf, nil
171}
172
173// MarshalIndent is like [Marshal] but applies [Indent] to format the output.
174// Each JSON element in the output will begin on a new line beginning with prefix
175// followed by one or more copies of indent according to the indentation nesting.
176func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
177	b, err := Marshal(v)
178	if err != nil {
179		return nil, err
180	}
181	b2 := make([]byte, 0, indentGrowthFactor*len(b))
182	b2, err = appendIndent(b2, b, prefix, indent)
183	if err != nil {
184		return nil, err
185	}
186	return b2, nil
187}
188
189// Marshaler is the interface implemented by types that
190// can marshal themselves into valid JSON.
191type Marshaler interface {
192	MarshalJSON() ([]byte, error)
193}
194
195// An UnsupportedTypeError is returned by [Marshal] when attempting
196// to encode an unsupported value type.
197type UnsupportedTypeError struct {
198	Type reflect.Type
199}
200
201func (e *UnsupportedTypeError) Error() string {
202	return "json: unsupported type: " + e.Type.String()
203}
204
205// An UnsupportedValueError is returned by [Marshal] when attempting
206// to encode an unsupported value.
207type UnsupportedValueError struct {
208	Value reflect.Value
209	Str   string
210}
211
212func (e *UnsupportedValueError) Error() string {
213	return "json: unsupported value: " + e.Str
214}
215
216// Before Go 1.2, an InvalidUTF8Error was returned by [Marshal] when
217// attempting to encode a string value with invalid UTF-8 sequences.
218// As of Go 1.2, [Marshal] instead coerces the string to valid UTF-8 by
219// replacing invalid bytes with the Unicode replacement rune U+FFFD.
220//
221// Deprecated: No longer used; kept for compatibility.
222type InvalidUTF8Error struct {
223	S string // the whole string value that caused the error
224}
225
226func (e *InvalidUTF8Error) Error() string {
227	return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
228}
229
230// A MarshalerError represents an error from calling a
231// [Marshaler.MarshalJSON] or [encoding.TextMarshaler.MarshalText] method.
232type MarshalerError struct {
233	Type       reflect.Type
234	Err        error
235	sourceFunc string
236}
237
238func (e *MarshalerError) Error() string {
239	srcFunc := e.sourceFunc
240	if srcFunc == "" {
241		srcFunc = "MarshalJSON"
242	}
243	return "json: error calling " + srcFunc +
244		" for type " + e.Type.String() +
245		": " + e.Err.Error()
246}
247
248// Unwrap returns the underlying error.
249func (e *MarshalerError) Unwrap() error { return e.Err }
250
251const hex = "0123456789abcdef"
252
253// An encodeState encodes JSON into a bytes.Buffer.
254type encodeState struct {
255	bytes.Buffer // accumulated output
256
257	// Keep track of what pointers we've seen in the current recursive call
258	// path, to avoid cycles that could lead to a stack overflow. Only do
259	// the relatively expensive map operations if ptrLevel is larger than
260	// startDetectingCyclesAfter, so that we skip the work if we're within a
261	// reasonable amount of nested pointers deep.
262	ptrLevel uint
263	ptrSeen  map[any]struct{}
264}
265
266const startDetectingCyclesAfter = 1000
267
268var encodeStatePool sync.Pool
269
270func newEncodeState() *encodeState {
271	if v := encodeStatePool.Get(); v != nil {
272		e := v.(*encodeState)
273		e.Reset()
274		if len(e.ptrSeen) > 0 {
275			panic("ptrEncoder.encode should have emptied ptrSeen via defers")
276		}
277		e.ptrLevel = 0
278		return e
279	}
280	return &encodeState{ptrSeen: make(map[any]struct{})}
281}
282
283// jsonError is an error wrapper type for internal use only.
284// Panics with errors are wrapped in jsonError so that the top-level recover
285// can distinguish intentional panics from this package.
286type jsonError struct{ error }
287
288func (e *encodeState) marshal(v any, opts encOpts) (err error) {
289	defer func() {
290		if r := recover(); r != nil {
291			if je, ok := r.(jsonError); ok {
292				err = je.error
293			} else {
294				panic(r)
295			}
296		}
297	}()
298	e.reflectValue(reflect.ValueOf(v), opts)
299	return nil
300}
301
302// error aborts the encoding by panicking with err wrapped in jsonError.
303func (e *encodeState) error(err error) {
304	panic(jsonError{err})
305}
306
307func isEmptyValue(v reflect.Value) bool {
308	switch v.Kind() {
309	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
310		return v.Len() == 0
311	case reflect.Bool,
312		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
313		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
314		reflect.Float32, reflect.Float64,
315		reflect.Interface, reflect.Pointer:
316		return v.IsZero()
317	}
318	return false
319}
320
321func (e *encodeState) reflectValue(v reflect.Value, opts encOpts) {
322	valueEncoder(v)(e, v, opts)
323}
324
325type encOpts struct {
326	// quoted causes primitive fields to be encoded inside JSON strings.
327	quoted bool
328	// escapeHTML causes '<', '>', and '&' to be escaped in JSON strings.
329	escapeHTML bool
330}
331
332type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts)
333
334var encoderCache sync.Map // map[reflect.Type]encoderFunc
335
336func valueEncoder(v reflect.Value) encoderFunc {
337	if !v.IsValid() {
338		return invalidValueEncoder
339	}
340	return typeEncoder(v.Type())
341}
342
343func typeEncoder(t reflect.Type) encoderFunc {
344	if fi, ok := encoderCache.Load(t); ok {
345		return fi.(encoderFunc)
346	}
347
348	// To deal with recursive types, populate the map with an
349	// indirect func before we build it. This type waits on the
350	// real func (f) to be ready and then calls it. This indirect
351	// func is only used for recursive types.
352	var (
353		wg sync.WaitGroup
354		f  encoderFunc
355	)
356	wg.Add(1)
357	fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value, opts encOpts) {
358		wg.Wait()
359		f(e, v, opts)
360	}))
361	if loaded {
362		return fi.(encoderFunc)
363	}
364
365	// Compute the real encoder and replace the indirect func with it.
366	f = newTypeEncoder(t, true)
367	wg.Done()
368	encoderCache.Store(t, f)
369	return f
370}
371
372var (
373	marshalerType     = reflect.TypeFor[Marshaler]()
374	textMarshalerType = reflect.TypeFor[encoding.TextMarshaler]()
375)
376
377// newTypeEncoder constructs an encoderFunc for a type.
378// The returned encoder only checks CanAddr when allowAddr is true.
379func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
380	// If we have a non-pointer value whose type implements
381	// Marshaler with a value receiver, then we're better off taking
382	// the address of the value - otherwise we end up with an
383	// allocation as we cast the value to an interface.
384	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(marshalerType) {
385		return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
386	}
387	if t.Implements(marshalerType) {
388		return marshalerEncoder
389	}
390	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(textMarshalerType) {
391		return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
392	}
393	if t.Implements(textMarshalerType) {
394		return textMarshalerEncoder
395	}
396
397	switch t.Kind() {
398	case reflect.Bool:
399		return boolEncoder
400	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
401		return intEncoder
402	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
403		return uintEncoder
404	case reflect.Float32:
405		return float32Encoder
406	case reflect.Float64:
407		return float64Encoder
408	case reflect.String:
409		return stringEncoder
410	case reflect.Interface:
411		return interfaceEncoder
412	case reflect.Struct:
413		return newStructEncoder(t)
414	case reflect.Map:
415		return newMapEncoder(t)
416	case reflect.Slice:
417		return newSliceEncoder(t)
418	case reflect.Array:
419		return newArrayEncoder(t)
420	case reflect.Pointer:
421		return newPtrEncoder(t)
422	default:
423		return unsupportedTypeEncoder
424	}
425}
426
427func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) {
428	e.WriteString("null")
429}
430
431func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
432	if v.Kind() == reflect.Pointer && v.IsNil() {
433		e.WriteString("null")
434		return
435	}
436	m, ok := v.Interface().(Marshaler)
437	if !ok {
438		e.WriteString("null")
439		return
440	}
441	b, err := m.MarshalJSON()
442	if err == nil {
443		e.Grow(len(b))
444		out := e.AvailableBuffer()
445		out, err = appendCompact(out, b, opts.escapeHTML)
446		e.Buffer.Write(out)
447	}
448	if err != nil {
449		e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
450	}
451}
452
453func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
454	va := v.Addr()
455	if va.IsNil() {
456		e.WriteString("null")
457		return
458	}
459	m := va.Interface().(Marshaler)
460	b, err := m.MarshalJSON()
461	if err == nil {
462		e.Grow(len(b))
463		out := e.AvailableBuffer()
464		out, err = appendCompact(out, b, opts.escapeHTML)
465		e.Buffer.Write(out)
466	}
467	if err != nil {
468		e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
469	}
470}
471
472func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
473	if v.Kind() == reflect.Pointer && v.IsNil() {
474		e.WriteString("null")
475		return
476	}
477	m, ok := v.Interface().(encoding.TextMarshaler)
478	if !ok {
479		e.WriteString("null")
480		return
481	}
482	b, err := m.MarshalText()
483	if err != nil {
484		e.error(&MarshalerError{v.Type(), err, "MarshalText"})
485	}
486	e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
487}
488
489func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
490	va := v.Addr()
491	if va.IsNil() {
492		e.WriteString("null")
493		return
494	}
495	m := va.Interface().(encoding.TextMarshaler)
496	b, err := m.MarshalText()
497	if err != nil {
498		e.error(&MarshalerError{v.Type(), err, "MarshalText"})
499	}
500	e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
501}
502
503func boolEncoder(e *encodeState, v reflect.Value, opts encOpts) {
504	b := e.AvailableBuffer()
505	b = mayAppendQuote(b, opts.quoted)
506	b = strconv.AppendBool(b, v.Bool())
507	b = mayAppendQuote(b, opts.quoted)
508	e.Write(b)
509}
510
511func intEncoder(e *encodeState, v reflect.Value, opts encOpts) {
512	b := e.AvailableBuffer()
513	b = mayAppendQuote(b, opts.quoted)
514	b = strconv.AppendInt(b, v.Int(), 10)
515	b = mayAppendQuote(b, opts.quoted)
516	e.Write(b)
517}
518
519func uintEncoder(e *encodeState, v reflect.Value, opts encOpts) {
520	b := e.AvailableBuffer()
521	b = mayAppendQuote(b, opts.quoted)
522	b = strconv.AppendUint(b, v.Uint(), 10)
523	b = mayAppendQuote(b, opts.quoted)
524	e.Write(b)
525}
526
527type floatEncoder int // number of bits
528
529func (bits floatEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
530	f := v.Float()
531	if math.IsInf(f, 0) || math.IsNaN(f) {
532		e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
533	}
534
535	// Convert as if by ES6 number to string conversion.
536	// This matches most other JSON generators.
537	// See golang.org/issue/6384 and golang.org/issue/14135.
538	// Like fmt %g, but the exponent cutoffs are different
539	// and exponents themselves are not padded to two digits.
540	b := e.AvailableBuffer()
541	b = mayAppendQuote(b, opts.quoted)
542	abs := math.Abs(f)
543	fmt := byte('f')
544	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
545	if abs != 0 {
546		if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
547			fmt = 'e'
548		}
549	}
550	b = strconv.AppendFloat(b, f, fmt, -1, int(bits))
551	if fmt == 'e' {
552		// clean up e-09 to e-9
553		n := len(b)
554		if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
555			b[n-2] = b[n-1]
556			b = b[:n-1]
557		}
558	}
559	b = mayAppendQuote(b, opts.quoted)
560	e.Write(b)
561}
562
563var (
564	float32Encoder = (floatEncoder(32)).encode
565	float64Encoder = (floatEncoder(64)).encode
566)
567
568func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
569	if v.Type() == numberType {
570		numStr := v.String()
571		// In Go1.5 the empty string encodes to "0", while this is not a valid number literal
572		// we keep compatibility so check validity after this.
573		if numStr == "" {
574			numStr = "0" // Number's zero-val
575		}
576		if !isValidNumber(numStr) {
577			e.error(fmt.Errorf("json: invalid number literal %q", numStr))
578		}
579		b := e.AvailableBuffer()
580		b = mayAppendQuote(b, opts.quoted)
581		b = append(b, numStr...)
582		b = mayAppendQuote(b, opts.quoted)
583		e.Write(b)
584		return
585	}
586	if opts.quoted {
587		b := appendString(nil, v.String(), opts.escapeHTML)
588		e.Write(appendString(e.AvailableBuffer(), b, false)) // no need to escape again since it is already escaped
589	} else {
590		e.Write(appendString(e.AvailableBuffer(), v.String(), opts.escapeHTML))
591	}
592}
593
594// isValidNumber reports whether s is a valid JSON number literal.
595//
596// isValidNumber should be an internal detail,
597// but widely used packages access it using linkname.
598// Notable members of the hall of shame include:
599//   - github.com/bytedance/sonic
600//
601// Do not remove or change the type signature.
602// See go.dev/issue/67401.
603//
604//go:linkname isValidNumber
605func isValidNumber(s string) bool {
606	// This function implements the JSON numbers grammar.
607	// See https://tools.ietf.org/html/rfc7159#section-6
608	// and https://www.json.org/img/number.png
609
610	if s == "" {
611		return false
612	}
613
614	// Optional -
615	if s[0] == '-' {
616		s = s[1:]
617		if s == "" {
618			return false
619		}
620	}
621
622	// Digits
623	switch {
624	default:
625		return false
626
627	case s[0] == '0':
628		s = s[1:]
629
630	case '1' <= s[0] && s[0] <= '9':
631		s = s[1:]
632		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
633			s = s[1:]
634		}
635	}
636
637	// . followed by 1 or more digits.
638	if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
639		s = s[2:]
640		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
641			s = s[1:]
642		}
643	}
644
645	// e or E followed by an optional - or + and
646	// 1 or more digits.
647	if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
648		s = s[1:]
649		if s[0] == '+' || s[0] == '-' {
650			s = s[1:]
651			if s == "" {
652				return false
653			}
654		}
655		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
656			s = s[1:]
657		}
658	}
659
660	// Make sure we are at the end.
661	return s == ""
662}
663
664func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) {
665	if v.IsNil() {
666		e.WriteString("null")
667		return
668	}
669	e.reflectValue(v.Elem(), opts)
670}
671
672func unsupportedTypeEncoder(e *encodeState, v reflect.Value, _ encOpts) {
673	e.error(&UnsupportedTypeError{v.Type()})
674}
675
676type structEncoder struct {
677	fields structFields
678}
679
680type structFields struct {
681	list         []field
682	byExactName  map[string]*field
683	byFoldedName map[string]*field
684}
685
686func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
687	next := byte('{')
688FieldLoop:
689	for i := range se.fields.list {
690		f := &se.fields.list[i]
691
692		// Find the nested struct field by following f.index.
693		fv := v
694		for _, i := range f.index {
695			if fv.Kind() == reflect.Pointer {
696				if fv.IsNil() {
697					continue FieldLoop
698				}
699				fv = fv.Elem()
700			}
701			fv = fv.Field(i)
702		}
703
704		if f.omitEmpty && isEmptyValue(fv) {
705			continue
706		}
707		e.WriteByte(next)
708		next = ','
709		if opts.escapeHTML {
710			e.WriteString(f.nameEscHTML)
711		} else {
712			e.WriteString(f.nameNonEsc)
713		}
714		opts.quoted = f.quoted
715		f.encoder(e, fv, opts)
716	}
717	if next == '{' {
718		e.WriteString("{}")
719	} else {
720		e.WriteByte('}')
721	}
722}
723
724func newStructEncoder(t reflect.Type) encoderFunc {
725	se := structEncoder{fields: cachedTypeFields(t)}
726	return se.encode
727}
728
729type mapEncoder struct {
730	elemEnc encoderFunc
731}
732
733func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
734	if v.IsNil() {
735		e.WriteString("null")
736		return
737	}
738	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
739		// We're a large number of nested ptrEncoder.encode calls deep;
740		// start checking if we've run into a pointer cycle.
741		ptr := v.UnsafePointer()
742		if _, ok := e.ptrSeen[ptr]; ok {
743			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
744		}
745		e.ptrSeen[ptr] = struct{}{}
746		defer delete(e.ptrSeen, ptr)
747	}
748	e.WriteByte('{')
749
750	// Extract and sort the keys.
751	var (
752		sv  = make([]reflectWithString, v.Len())
753		mi  = v.MapRange()
754		err error
755	)
756	for i := 0; mi.Next(); i++ {
757		if sv[i].ks, err = resolveKeyName(mi.Key()); err != nil {
758			e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
759		}
760		sv[i].v = mi.Value()
761	}
762	slices.SortFunc(sv, func(i, j reflectWithString) int {
763		return strings.Compare(i.ks, j.ks)
764	})
765
766	for i, kv := range sv {
767		if i > 0 {
768			e.WriteByte(',')
769		}
770		e.Write(appendString(e.AvailableBuffer(), kv.ks, opts.escapeHTML))
771		e.WriteByte(':')
772		me.elemEnc(e, kv.v, opts)
773	}
774	e.WriteByte('}')
775	e.ptrLevel--
776}
777
778func newMapEncoder(t reflect.Type) encoderFunc {
779	switch t.Key().Kind() {
780	case reflect.String,
781		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
782		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
783	default:
784		if !t.Key().Implements(textMarshalerType) {
785			return unsupportedTypeEncoder
786		}
787	}
788	me := mapEncoder{typeEncoder(t.Elem())}
789	return me.encode
790}
791
792func encodeByteSlice(e *encodeState, v reflect.Value, _ encOpts) {
793	if v.IsNil() {
794		e.WriteString("null")
795		return
796	}
797
798	s := v.Bytes()
799	b := e.AvailableBuffer()
800	b = append(b, '"')
801	b = base64.StdEncoding.AppendEncode(b, s)
802	b = append(b, '"')
803	e.Write(b)
804}
805
806// sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil.
807type sliceEncoder struct {
808	arrayEnc encoderFunc
809}
810
811func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
812	if v.IsNil() {
813		e.WriteString("null")
814		return
815	}
816	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
817		// We're a large number of nested ptrEncoder.encode calls deep;
818		// start checking if we've run into a pointer cycle.
819		// Here we use a struct to memorize the pointer to the first element of the slice
820		// and its length.
821		ptr := struct {
822			ptr interface{} // always an unsafe.Pointer, but avoids a dependency on package unsafe
823			len int
824		}{v.UnsafePointer(), v.Len()}
825		if _, ok := e.ptrSeen[ptr]; ok {
826			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
827		}
828		e.ptrSeen[ptr] = struct{}{}
829		defer delete(e.ptrSeen, ptr)
830	}
831	se.arrayEnc(e, v, opts)
832	e.ptrLevel--
833}
834
835func newSliceEncoder(t reflect.Type) encoderFunc {
836	// Byte slices get special treatment; arrays don't.
837	if t.Elem().Kind() == reflect.Uint8 {
838		p := reflect.PointerTo(t.Elem())
839		if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) {
840			return encodeByteSlice
841		}
842	}
843	enc := sliceEncoder{newArrayEncoder(t)}
844	return enc.encode
845}
846
847type arrayEncoder struct {
848	elemEnc encoderFunc
849}
850
851func (ae arrayEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
852	e.WriteByte('[')
853	n := v.Len()
854	for i := 0; i < n; i++ {
855		if i > 0 {
856			e.WriteByte(',')
857		}
858		ae.elemEnc(e, v.Index(i), opts)
859	}
860	e.WriteByte(']')
861}
862
863func newArrayEncoder(t reflect.Type) encoderFunc {
864	enc := arrayEncoder{typeEncoder(t.Elem())}
865	return enc.encode
866}
867
868type ptrEncoder struct {
869	elemEnc encoderFunc
870}
871
872func (pe ptrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
873	if v.IsNil() {
874		e.WriteString("null")
875		return
876	}
877	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
878		// We're a large number of nested ptrEncoder.encode calls deep;
879		// start checking if we've run into a pointer cycle.
880		ptr := v.Interface()
881		if _, ok := e.ptrSeen[ptr]; ok {
882			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
883		}
884		e.ptrSeen[ptr] = struct{}{}
885		defer delete(e.ptrSeen, ptr)
886	}
887	pe.elemEnc(e, v.Elem(), opts)
888	e.ptrLevel--
889}
890
891func newPtrEncoder(t reflect.Type) encoderFunc {
892	enc := ptrEncoder{typeEncoder(t.Elem())}
893	return enc.encode
894}
895
896type condAddrEncoder struct {
897	canAddrEnc, elseEnc encoderFunc
898}
899
900func (ce condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
901	if v.CanAddr() {
902		ce.canAddrEnc(e, v, opts)
903	} else {
904		ce.elseEnc(e, v, opts)
905	}
906}
907
908// newCondAddrEncoder returns an encoder that checks whether its value
909// CanAddr and delegates to canAddrEnc if so, else to elseEnc.
910func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
911	enc := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
912	return enc.encode
913}
914
915func isValidTag(s string) bool {
916	if s == "" {
917		return false
918	}
919	for _, c := range s {
920		switch {
921		case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
922			// Backslash and quote chars are reserved, but
923			// otherwise any punctuation chars are allowed
924			// in a tag name.
925		case !unicode.IsLetter(c) && !unicode.IsDigit(c):
926			return false
927		}
928	}
929	return true
930}
931
932func typeByIndex(t reflect.Type, index []int) reflect.Type {
933	for _, i := range index {
934		if t.Kind() == reflect.Pointer {
935			t = t.Elem()
936		}
937		t = t.Field(i).Type
938	}
939	return t
940}
941
942type reflectWithString struct {
943	v  reflect.Value
944	ks string
945}
946
947func resolveKeyName(k reflect.Value) (string, error) {
948	if k.Kind() == reflect.String {
949		return k.String(), nil
950	}
951	if tm, ok := k.Interface().(encoding.TextMarshaler); ok {
952		if k.Kind() == reflect.Pointer && k.IsNil() {
953			return "", nil
954		}
955		buf, err := tm.MarshalText()
956		return string(buf), err
957	}
958	switch k.Kind() {
959	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
960		return strconv.FormatInt(k.Int(), 10), nil
961	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
962		return strconv.FormatUint(k.Uint(), 10), nil
963	}
964	panic("unexpected map key type")
965}
966
967func appendString[Bytes []byte | string](dst []byte, src Bytes, escapeHTML bool) []byte {
968	dst = append(dst, '"')
969	start := 0
970	for i := 0; i < len(src); {
971		if b := src[i]; b < utf8.RuneSelf {
972			if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
973				i++
974				continue
975			}
976			dst = append(dst, src[start:i]...)
977			switch b {
978			case '\\', '"':
979				dst = append(dst, '\\', b)
980			case '\b':
981				dst = append(dst, '\\', 'b')
982			case '\f':
983				dst = append(dst, '\\', 'f')
984			case '\n':
985				dst = append(dst, '\\', 'n')
986			case '\r':
987				dst = append(dst, '\\', 'r')
988			case '\t':
989				dst = append(dst, '\\', 't')
990			default:
991				// This encodes bytes < 0x20 except for \b, \f, \n, \r and \t.
992				// If escapeHTML is set, it also escapes <, >, and &
993				// because they can lead to security holes when
994				// user-controlled strings are rendered into JSON
995				// and served to some browsers.
996				dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
997			}
998			i++
999			start = i
1000			continue
1001		}
1002		// TODO(https://go.dev/issue/56948): Use generic utf8 functionality.
1003		// For now, cast only a small portion of byte slices to a string
1004		// so that it can be stack allocated. This slows down []byte slightly
1005		// due to the extra copy, but keeps string performance roughly the same.
1006		n := len(src) - i
1007		if n > utf8.UTFMax {
1008			n = utf8.UTFMax
1009		}
1010		c, size := utf8.DecodeRuneInString(string(src[i : i+n]))
1011		if c == utf8.RuneError && size == 1 {
1012			dst = append(dst, src[start:i]...)
1013			dst = append(dst, `\ufffd`...)
1014			i += size
1015			start = i
1016			continue
1017		}
1018		// U+2028 is LINE SEPARATOR.
1019		// U+2029 is PARAGRAPH SEPARATOR.
1020		// They are both technically valid characters in JSON strings,
1021		// but don't work in JSONP, which has to be evaluated as JavaScript,
1022		// and can lead to security holes there. It is valid JSON to
1023		// escape them, so we do so unconditionally.
1024		// See https://en.wikipedia.org/wiki/JSON#Safety.
1025		if c == '\u2028' || c == '\u2029' {
1026			dst = append(dst, src[start:i]...)
1027			dst = append(dst, '\\', 'u', '2', '0', '2', hex[c&0xF])
1028			i += size
1029			start = i
1030			continue
1031		}
1032		i += size
1033	}
1034	dst = append(dst, src[start:]...)
1035	dst = append(dst, '"')
1036	return dst
1037}
1038
1039// A field represents a single field found in a struct.
1040type field struct {
1041	name      string
1042	nameBytes []byte // []byte(name)
1043
1044	nameNonEsc  string // `"` + name + `":`
1045	nameEscHTML string // `"` + HTMLEscape(name) + `":`
1046
1047	tag       bool
1048	index     []int
1049	typ       reflect.Type
1050	omitEmpty bool
1051	quoted    bool
1052
1053	encoder encoderFunc
1054}
1055
1056// typeFields returns a list of fields that JSON should recognize for the given type.
1057// The algorithm is breadth-first search over the set of structs to include - the top struct
1058// and then any reachable anonymous structs.
1059//
1060// typeFields should be an internal detail,
1061// but widely used packages access it using linkname.
1062// Notable members of the hall of shame include:
1063//   - github.com/bytedance/sonic
1064//
1065// Do not remove or change the type signature.
1066// See go.dev/issue/67401.
1067//
1068//go:linkname typeFields
1069func typeFields(t reflect.Type) structFields {
1070	// Anonymous fields to explore at the current level and the next.
1071	current := []field{}
1072	next := []field{{typ: t}}
1073
1074	// Count of queued names for current level and the next.
1075	var count, nextCount map[reflect.Type]int
1076
1077	// Types already visited at an earlier level.
1078	visited := map[reflect.Type]bool{}
1079
1080	// Fields found.
1081	var fields []field
1082
1083	// Buffer to run appendHTMLEscape on field names.
1084	var nameEscBuf []byte
1085
1086	for len(next) > 0 {
1087		current, next = next, current[:0]
1088		count, nextCount = nextCount, map[reflect.Type]int{}
1089
1090		for _, f := range current {
1091			if visited[f.typ] {
1092				continue
1093			}
1094			visited[f.typ] = true
1095
1096			// Scan f.typ for fields to include.
1097			for i := 0; i < f.typ.NumField(); i++ {
1098				sf := f.typ.Field(i)
1099				if sf.Anonymous {
1100					t := sf.Type
1101					if t.Kind() == reflect.Pointer {
1102						t = t.Elem()
1103					}
1104					if !sf.IsExported() && t.Kind() != reflect.Struct {
1105						// Ignore embedded fields of unexported non-struct types.
1106						continue
1107					}
1108					// Do not ignore embedded fields of unexported struct types
1109					// since they may have exported fields.
1110				} else if !sf.IsExported() {
1111					// Ignore unexported non-embedded fields.
1112					continue
1113				}
1114				tag := sf.Tag.Get("json")
1115				if tag == "-" {
1116					continue
1117				}
1118				name, opts := parseTag(tag)
1119				if !isValidTag(name) {
1120					name = ""
1121				}
1122				index := make([]int, len(f.index)+1)
1123				copy(index, f.index)
1124				index[len(f.index)] = i
1125
1126				ft := sf.Type
1127				if ft.Name() == "" && ft.Kind() == reflect.Pointer {
1128					// Follow pointer.
1129					ft = ft.Elem()
1130				}
1131
1132				// Only strings, floats, integers, and booleans can be quoted.
1133				quoted := false
1134				if opts.Contains("string") {
1135					switch ft.Kind() {
1136					case reflect.Bool,
1137						reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
1138						reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
1139						reflect.Float32, reflect.Float64,
1140						reflect.String:
1141						quoted = true
1142					}
1143				}
1144
1145				// Record found field and index sequence.
1146				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
1147					tagged := name != ""
1148					if name == "" {
1149						name = sf.Name
1150					}
1151					field := field{
1152						name:      name,
1153						tag:       tagged,
1154						index:     index,
1155						typ:       ft,
1156						omitEmpty: opts.Contains("omitempty"),
1157						quoted:    quoted,
1158					}
1159					field.nameBytes = []byte(field.name)
1160
1161					// Build nameEscHTML and nameNonEsc ahead of time.
1162					nameEscBuf = appendHTMLEscape(nameEscBuf[:0], field.nameBytes)
1163					field.nameEscHTML = `"` + string(nameEscBuf) + `":`
1164					field.nameNonEsc = `"` + field.name + `":`
1165
1166					fields = append(fields, field)
1167					if count[f.typ] > 1 {
1168						// If there were multiple instances, add a second,
1169						// so that the annihilation code will see a duplicate.
1170						// It only cares about the distinction between 1 and 2,
1171						// so don't bother generating any more copies.
1172						fields = append(fields, fields[len(fields)-1])
1173					}
1174					continue
1175				}
1176
1177				// Record new anonymous struct to explore in next round.
1178				nextCount[ft]++
1179				if nextCount[ft] == 1 {
1180					next = append(next, field{name: ft.Name(), index: index, typ: ft})
1181				}
1182			}
1183		}
1184	}
1185
1186	slices.SortFunc(fields, func(a, b field) int {
1187		// sort field by name, breaking ties with depth, then
1188		// breaking ties with "name came from json tag", then
1189		// breaking ties with index sequence.
1190		if c := strings.Compare(a.name, b.name); c != 0 {
1191			return c
1192		}
1193		if c := cmp.Compare(len(a.index), len(b.index)); c != 0 {
1194			return c
1195		}
1196		if a.tag != b.tag {
1197			if a.tag {
1198				return -1
1199			}
1200			return +1
1201		}
1202		return slices.Compare(a.index, b.index)
1203	})
1204
1205	// Delete all fields that are hidden by the Go rules for embedded fields,
1206	// except that fields with JSON tags are promoted.
1207
1208	// The fields are sorted in primary order of name, secondary order
1209	// of field index length. Loop over names; for each name, delete
1210	// hidden fields by choosing the one dominant field that survives.
1211	out := fields[:0]
1212	for advance, i := 0, 0; i < len(fields); i += advance {
1213		// One iteration per name.
1214		// Find the sequence of fields with the name of this first field.
1215		fi := fields[i]
1216		name := fi.name
1217		for advance = 1; i+advance < len(fields); advance++ {
1218			fj := fields[i+advance]
1219			if fj.name != name {
1220				break
1221			}
1222		}
1223		if advance == 1 { // Only one field with this name
1224			out = append(out, fi)
1225			continue
1226		}
1227		dominant, ok := dominantField(fields[i : i+advance])
1228		if ok {
1229			out = append(out, dominant)
1230		}
1231	}
1232
1233	fields = out
1234	slices.SortFunc(fields, func(i, j field) int {
1235		return slices.Compare(i.index, j.index)
1236	})
1237
1238	for i := range fields {
1239		f := &fields[i]
1240		f.encoder = typeEncoder(typeByIndex(t, f.index))
1241	}
1242	exactNameIndex := make(map[string]*field, len(fields))
1243	foldedNameIndex := make(map[string]*field, len(fields))
1244	for i, field := range fields {
1245		exactNameIndex[field.name] = &fields[i]
1246		// For historical reasons, first folded match takes precedence.
1247		if _, ok := foldedNameIndex[string(foldName(field.nameBytes))]; !ok {
1248			foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i]
1249		}
1250	}
1251	return structFields{fields, exactNameIndex, foldedNameIndex}
1252}
1253
1254// dominantField looks through the fields, all of which are known to
1255// have the same name, to find the single field that dominates the
1256// others using Go's embedding rules, modified by the presence of
1257// JSON tags. If there are multiple top-level fields, the boolean
1258// will be false: This condition is an error in Go and we skip all
1259// the fields.
1260func dominantField(fields []field) (field, bool) {
1261	// The fields are sorted in increasing index-length order, then by presence of tag.
1262	// That means that the first field is the dominant one. We need only check
1263	// for error cases: two fields at top level, either both tagged or neither tagged.
1264	if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
1265		return field{}, false
1266	}
1267	return fields[0], true
1268}
1269
1270var fieldCache sync.Map // map[reflect.Type]structFields
1271
1272// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
1273func cachedTypeFields(t reflect.Type) structFields {
1274	if f, ok := fieldCache.Load(t); ok {
1275		return f.(structFields)
1276	}
1277	f, _ := fieldCache.LoadOrStore(t, typeFields(t))
1278	return f.(structFields)
1279}
1280
1281func mayAppendQuote(b []byte, quoted bool) []byte {
1282	if quoted {
1283		b = append(b, '"')
1284	}
1285	return b
1286}
1287