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