Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Package json implements encoding and decoding of JSON objects as defined in | 5 // Package json implements encoding and decoding of JSON objects as defined in |
6 // RFC 4627. The mapping between JSON objects and Go values is described | 6 // RFC 4627. The mapping between JSON objects and Go values is described |
7 // in the documentation for the Marshal and Unmarshal functions. | 7 // in the documentation for the Marshal and Unmarshal functions. |
8 // | 8 // |
9 // See "JSON and Go" for an introduction to this package: | 9 // See "JSON and Go" for an introduction to this package: |
10 // http://golang.org/doc/articles/json_and_go.html | 10 // http://golang.org/doc/articles/json_and_go.html |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
338 var wg sync.WaitGroup | 338 var wg sync.WaitGroup |
339 wg.Add(1) | 339 wg.Add(1) |
340 encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) { | 340 encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) { |
341 wg.Wait() | 341 wg.Wait() |
342 f(e, v, quoted) | 342 f(e, v, quoted) |
343 } | 343 } |
344 encoderCache.Unlock() | 344 encoderCache.Unlock() |
345 | 345 |
346 // Compute fields without lock. | 346 // Compute fields without lock. |
347 // Might duplicate effort but won't hold other computations back. | 347 // Might duplicate effort but won't hold other computations back. |
348 » f = buildTypeEncoder(t, vx) | 348 » f = newTypeEncoder(t, vx) |
349 wg.Done() | 349 wg.Done() |
350 encoderCache.Lock() | 350 encoderCache.Lock() |
351 encoderCache.m[t] = f | 351 encoderCache.m[t] = f |
352 encoderCache.Unlock() | 352 encoderCache.Unlock() |
353 return f | 353 return f |
354 } | 354 } |
355 | 355 |
356 // buildTypeEncoder constructs an encoderFunc for a type. | 356 // newTypeEncoder constructs an encoderFunc for a type. |
rsc
2013/08/09 02:04:13
s/build/new/ throughout
| |
357 // The provided vx is an example value of type t. It's the first seen | 357 // The provided vx is an example value of type t. It's the first seen |
358 // value of that type and should not be used to encode. It may be | 358 // value of that type and should not be used to encode. It may be |
359 // zero. | 359 // zero. |
360 func buildTypeEncoder(t reflect.Type, vx reflect.Value) encoderFunc { | 360 func newTypeEncoder(t reflect.Type, vx reflect.Value) encoderFunc { |
361 if !vx.IsValid() { | 361 if !vx.IsValid() { |
362 vx = reflect.New(t).Elem() | 362 vx = reflect.New(t).Elem() |
363 } | 363 } |
364 _, ok := vx.Interface().(Marshaler) | 364 _, ok := vx.Interface().(Marshaler) |
365 if ok { | 365 if ok { |
366 return valueIsMarshallerEncoder | 366 return valueIsMarshallerEncoder |
367 } | 367 } |
368 // T doesn't match the interface. Check against *T too. | 368 // T doesn't match the interface. Check against *T too. |
369 if vx.Kind() != reflect.Ptr && vx.CanAddr() { | 369 if vx.Kind() != reflect.Ptr && vx.CanAddr() { |
370 _, ok = vx.Addr().Interface().(Marshaler) | 370 _, ok = vx.Addr().Interface().(Marshaler) |
(...skipping 10 matching lines...) Expand all Loading... | |
381 return uintEncoder | 381 return uintEncoder |
382 case reflect.Float32: | 382 case reflect.Float32: |
383 return float32Encoder | 383 return float32Encoder |
384 case reflect.Float64: | 384 case reflect.Float64: |
385 return float64Encoder | 385 return float64Encoder |
386 case reflect.String: | 386 case reflect.String: |
387 return stringEncoder | 387 return stringEncoder |
388 case reflect.Interface: | 388 case reflect.Interface: |
389 return interfaceEncoder | 389 return interfaceEncoder |
390 case reflect.Struct: | 390 case reflect.Struct: |
391 » » return buildStructEncoder(t, vx) | 391 » » return newStructEncoder(t, vx) |
392 case reflect.Map: | 392 case reflect.Map: |
393 » » return buildMapEncoder(t, vx) | 393 » » return newMapEncoder(t, vx) |
394 case reflect.Slice: | 394 case reflect.Slice: |
395 » » return buildSliceEncoder(t, vx) | 395 » » return newSliceEncoder(t, vx) |
396 case reflect.Array: | 396 case reflect.Array: |
397 » » return buildArrayEncoder(t, vx) | 397 » » return newArrayEncoder(t, vx) |
398 case reflect.Ptr: | 398 case reflect.Ptr: |
399 » » return buildPtrEncoder(t, vx) | 399 » » return newPtrEncoder(t, vx) |
400 default: | 400 default: |
401 return unsupportedTypeEncoder | 401 return unsupportedTypeEncoder |
402 } | 402 } |
403 } | 403 } |
404 | 404 |
405 func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) { | 405 func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) { |
406 e.WriteString("null") | 406 e.WriteString("null") |
407 } | 407 } |
408 | 408 |
409 func valueIsMarshallerEncoder(e *encodeState, v reflect.Value, quoted bool) { | 409 func valueIsMarshallerEncoder(e *encodeState, v reflect.Value, quoted bool) { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
523 return | 523 return |
524 } | 524 } |
525 e.reflectValue(v.Elem()) | 525 e.reflectValue(v.Elem()) |
526 } | 526 } |
527 | 527 |
528 func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) { | 528 func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) { |
529 e.error(&UnsupportedTypeError{v.Type()}) | 529 e.error(&UnsupportedTypeError{v.Type()}) |
530 } | 530 } |
531 | 531 |
532 type structEncoder struct { | 532 type structEncoder struct { |
533 » fields []field | 533 » fields []field |
534 » fieldFuncs []encoderFunc | 534 » fieldEncs []encoderFunc |
rsc
2013/08/09 02:04:13
fieldEncs (match all the elemEnc)
| |
535 } | 535 } |
536 | 536 |
537 func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) { | 537 func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) { |
538 e.WriteByte('{') | 538 e.WriteByte('{') |
539 first := true | 539 first := true |
540 for i, f := range se.fields { | 540 for i, f := range se.fields { |
541 fv := fieldByIndex(v, f.index) | 541 fv := fieldByIndex(v, f.index) |
542 if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) { | 542 if !fv.IsValid() || f.omitEmpty && isEmptyValue(fv) { |
543 continue | 543 continue |
544 } | 544 } |
545 if first { | 545 if first { |
546 first = false | 546 first = false |
547 } else { | 547 } else { |
548 e.WriteByte(',') | 548 e.WriteByte(',') |
549 } | 549 } |
550 e.string(f.name) | 550 e.string(f.name) |
551 e.WriteByte(':') | 551 e.WriteByte(':') |
552 » » if tenc := se.fieldFuncs[i]; tenc != nil { | 552 » » if tenc := se.fieldEncs[i]; tenc != nil { |
553 tenc(e, fv, f.quoted) | 553 tenc(e, fv, f.quoted) |
554 } else { | 554 } else { |
555 // Slower path. | 555 // Slower path. |
556 e.reflectValue(fv) | 556 e.reflectValue(fv) |
557 } | 557 } |
558 } | 558 } |
559 e.WriteByte('}') | 559 e.WriteByte('}') |
560 } | 560 } |
561 | 561 |
562 func buildStructEncoder(t reflect.Type, vx reflect.Value) encoderFunc { | 562 func newStructEncoder(t reflect.Type, vx reflect.Value) encoderFunc { |
563 fields := cachedTypeFields(t) | 563 fields := cachedTypeFields(t) |
564 se := &structEncoder{ | 564 se := &structEncoder{ |
565 » » fields: fields, | 565 » » fields: fields, |
566 » » fieldFuncs: make([]encoderFunc, len(fields)), | 566 » » fieldEncs: make([]encoderFunc, len(fields)), |
567 } | 567 } |
568 for i, f := range fields { | 568 for i, f := range fields { |
569 vxf := fieldByIndex(vx, f.index) | 569 vxf := fieldByIndex(vx, f.index) |
570 if vxf.IsValid() { | 570 if vxf.IsValid() { |
571 » » » se.fieldFuncs[i] = typeEncoder(vxf.Type(), vxf) | 571 » » » se.fieldEncs[i] = typeEncoder(vxf.Type(), vxf) |
572 } | 572 } |
573 } | 573 } |
574 return se.encode | 574 return se.encode |
575 } | 575 } |
576 | 576 |
577 type mapEncoder struct { | 577 type mapEncoder struct { |
578 elemEnc encoderFunc | 578 elemEnc encoderFunc |
579 } | 579 } |
580 | 580 |
581 func (me *mapEncoder) encode(e *encodeState, v reflect.Value, _ bool) { | 581 func (me *mapEncoder) encode(e *encodeState, v reflect.Value, _ bool) { |
582 if v.IsNil() { | 582 if v.IsNil() { |
583 e.WriteString("null") | 583 e.WriteString("null") |
584 return | 584 return |
585 } | 585 } |
586 e.WriteByte('{') | 586 e.WriteByte('{') |
587 var sv stringValues = v.MapKeys() | 587 var sv stringValues = v.MapKeys() |
588 sort.Sort(sv) | 588 sort.Sort(sv) |
589 for i, k := range sv { | 589 for i, k := range sv { |
590 if i > 0 { | 590 if i > 0 { |
591 e.WriteByte(',') | 591 e.WriteByte(',') |
592 } | 592 } |
593 e.string(k.String()) | 593 e.string(k.String()) |
594 e.WriteByte(':') | 594 e.WriteByte(':') |
595 me.elemEnc(e, v.MapIndex(k), false) | 595 me.elemEnc(e, v.MapIndex(k), false) |
596 } | 596 } |
597 e.WriteByte('}') | 597 e.WriteByte('}') |
598 } | 598 } |
599 | 599 |
600 func buildMapEncoder(t reflect.Type, vx reflect.Value) encoderFunc { | 600 func newMapEncoder(t reflect.Type, vx reflect.Value) encoderFunc { |
601 if t.Key().Kind() != reflect.String { | 601 if t.Key().Kind() != reflect.String { |
602 return unsupportedTypeEncoder | 602 return unsupportedTypeEncoder |
603 } | 603 } |
604 me := &mapEncoder{typeEncoder(vx.Type().Elem(), reflect.Value{})} | 604 me := &mapEncoder{typeEncoder(vx.Type().Elem(), reflect.Value{})} |
605 return me.encode | 605 return me.encode |
606 } | 606 } |
607 | 607 |
608 func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) { | 608 func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) { |
609 if v.IsNil() { | 609 if v.IsNil() { |
610 e.WriteString("null") | 610 e.WriteString("null") |
(...skipping 11 matching lines...) Expand all Loading... | |
622 // buffer space. | 622 // buffer space. |
623 enc := base64.NewEncoder(base64.StdEncoding, e) | 623 enc := base64.NewEncoder(base64.StdEncoding, e) |
624 enc.Write(s) | 624 enc.Write(s) |
625 enc.Close() | 625 enc.Close() |
626 } | 626 } |
627 e.WriteByte('"') | 627 e.WriteByte('"') |
628 } | 628 } |
629 | 629 |
630 // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn' t nil. | 630 // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn' t nil. |
631 type sliceEncoder struct { | 631 type sliceEncoder struct { |
632 » arrayEncoder encoderFunc | 632 » arrayEnc encoderFunc |
rsc
2013/08/09 02:04:13
arrayEnc
| |
633 } | 633 } |
634 | 634 |
635 func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, _ bool) { | 635 func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, _ bool) { |
636 if v.IsNil() { | 636 if v.IsNil() { |
637 e.WriteString("null") | 637 e.WriteString("null") |
638 return | 638 return |
639 } | 639 } |
640 » se.arrayEncoder(e, v, false) | 640 » se.arrayEnc(e, v, false) |
641 } | 641 } |
642 | 642 |
643 func buildSliceEncoder(t reflect.Type, vx reflect.Value) encoderFunc { | 643 func newSliceEncoder(t reflect.Type, vx reflect.Value) encoderFunc { |
644 // Byte slices get special treatment; arrays don't. | 644 // Byte slices get special treatment; arrays don't. |
645 if vx.Type().Elem().Kind() == reflect.Uint8 { | 645 if vx.Type().Elem().Kind() == reflect.Uint8 { |
646 return encodeByteSlice | 646 return encodeByteSlice |
647 } | 647 } |
648 » enc := &sliceEncoder{buildArrayEncoder(t, vx)} | 648 » enc := &sliceEncoder{newArrayEncoder(t, vx)} |
649 return enc.encode | 649 return enc.encode |
650 } | 650 } |
651 | 651 |
652 type arrayEncoder struct { | 652 type arrayEncoder struct { |
653 elemEnc encoderFunc | 653 elemEnc encoderFunc |
654 } | 654 } |
655 | 655 |
656 func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, _ bool) { | 656 func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, _ bool) { |
657 e.WriteByte('[') | 657 e.WriteByte('[') |
658 n := v.Len() | 658 n := v.Len() |
659 for i := 0; i < n; i++ { | 659 for i := 0; i < n; i++ { |
660 if i > 0 { | 660 if i > 0 { |
661 e.WriteByte(',') | 661 e.WriteByte(',') |
662 } | 662 } |
663 ae.elemEnc(e, v.Index(i), false) | 663 ae.elemEnc(e, v.Index(i), false) |
664 } | 664 } |
665 e.WriteByte(']') | 665 e.WriteByte(']') |
666 } | 666 } |
667 | 667 |
668 func buildArrayEncoder(t reflect.Type, vx reflect.Value) encoderFunc { | 668 func newArrayEncoder(t reflect.Type, vx reflect.Value) encoderFunc { |
669 enc := &arrayEncoder{typeEncoder(t.Elem(), reflect.Value{})} | 669 enc := &arrayEncoder{typeEncoder(t.Elem(), reflect.Value{})} |
670 return enc.encode | 670 return enc.encode |
671 } | 671 } |
672 | 672 |
673 type ptrEncoder struct { | 673 type ptrEncoder struct { |
674 elemEnc encoderFunc | 674 elemEnc encoderFunc |
675 } | 675 } |
676 | 676 |
677 func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, _ bool) { | 677 func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, _ bool) { |
678 if v.IsNil() { | 678 if v.IsNil() { |
679 e.WriteString("null") | 679 e.WriteString("null") |
680 return | 680 return |
681 } | 681 } |
682 pe.elemEnc(e, v.Elem(), false) | 682 pe.elemEnc(e, v.Elem(), false) |
683 } | 683 } |
684 | 684 |
685 func buildPtrEncoder(t reflect.Type, vx reflect.Value) encoderFunc { | 685 func newPtrEncoder(t reflect.Type, vx reflect.Value) encoderFunc { |
686 enc := &ptrEncoder{typeEncoder(t.Elem(), reflect.Value{})} | 686 enc := &ptrEncoder{typeEncoder(t.Elem(), reflect.Value{})} |
687 return enc.encode | 687 return enc.encode |
688 } | 688 } |
689 | 689 |
690 func isValidTag(s string) bool { | 690 func isValidTag(s string) bool { |
691 if s == "" { | 691 if s == "" { |
692 return false | 692 return false |
693 } | 693 } |
694 for _, c := range s { | 694 for _, c := range s { |
695 switch { | 695 switch { |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1026 } | 1026 } |
1027 | 1027 |
1028 fieldCache.Lock() | 1028 fieldCache.Lock() |
1029 if fieldCache.m == nil { | 1029 if fieldCache.m == nil { |
1030 fieldCache.m = map[reflect.Type][]field{} | 1030 fieldCache.m = map[reflect.Type][]field{} |
1031 } | 1031 } |
1032 fieldCache.m[t] = f | 1032 fieldCache.m[t] = f |
1033 fieldCache.Unlock() | 1033 fieldCache.Unlock() |
1034 return f | 1034 return f |
1035 } | 1035 } |
LEFT | RIGHT |