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