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. | 6 // RFC 4627. |
7 // | 7 // |
8 // See "JSON and Go" for an introduction to this package: | 8 // See "JSON and Go" for an introduction to this package: |
9 // http://golang.org/doc/articles/json_and_go.html | 9 // http://golang.org/doc/articles/json_and_go.html |
10 package json | 10 package json |
11 | 11 |
12 import ( | 12 import ( |
13 "bytes" | 13 "bytes" |
14 "encoding/base64" | 14 "encoding/base64" |
15 "math" | 15 "math" |
16 "reflect" | 16 "reflect" |
17 "runtime" | 17 "runtime" |
18 "sort" | 18 "sort" |
19 "strconv" | 19 "strconv" |
| 20 "strings" |
20 "sync" | 21 "sync" |
| 22 "unicode" |
21 "unicode/utf8" | 23 "unicode/utf8" |
22 ) | 24 ) |
23 | 25 |
24 // Marshal returns the JSON encoding of v. | 26 // Marshal returns the JSON encoding of v. |
25 // | 27 // |
26 // Marshal traverses the value v recursively. | 28 // Marshal traverses the value v recursively. |
27 // If an encountered value implements the Marshaler interface | 29 // If an encountered value implements the Marshaler interface |
28 // and is not a nil pointer, Marshal calls its MarshalJSON method | 30 // and is not a nil pointer, Marshal calls its MarshalJSON method |
29 // to produce JSON. The nil pointer exception is not strictly necessary | 31 // to produce JSON. The nil pointer exception is not strictly necessary |
30 // but mimics a similar, necessary exception in the behavior of | 32 // but mimics a similar, necessary exception in the behavior of |
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 return | 424 return |
423 } | 425 } |
424 e.reflectValue(v.Elem()) | 426 e.reflectValue(v.Elem()) |
425 | 427 |
426 default: | 428 default: |
427 e.error(&UnsupportedTypeError{v.Type()}) | 429 e.error(&UnsupportedTypeError{v.Type()}) |
428 } | 430 } |
429 return | 431 return |
430 } | 432 } |
431 | 433 |
432 func isValidString(s string) bool { | |
433 escape := false // have we read a '\' character? | |
434 | |
435 for i := 0; i < len(s); { | |
436 if b := s[i]; b < utf8.RuneSelf { | |
437 switch { | |
438 case b == '\\' && escape == false: | |
439 escape = true | |
440 i++ | |
441 continue | |
442 case b == '"' && escape == false: | |
443 case b < 0x20: | |
444 return false | |
445 } | |
446 | |
447 escape = false | |
448 i++ | |
449 continue | |
450 } | |
451 c, size := utf8.DecodeRuneInString(s[i:]) | |
452 if c == utf8.RuneError && size == 1 { | |
453 return false | |
454 } | |
455 i += size | |
456 } | |
457 return escape == false | |
458 } | |
459 | |
460 func isValidTag(s string) bool { | 434 func isValidTag(s string) bool { |
461 if s == "" { | 435 if s == "" { |
462 return false | 436 return false |
463 } | 437 } |
464 » return isValidString(s) | 438 » for _, c := range s { |
| 439 » » switch { |
| 440 » » case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c): |
| 441 » » » // Backslash and quote chars are reserved, but |
| 442 » » » // otherwise any punctuation chars are allowed |
| 443 » » » // in a tag name. |
| 444 » » default: |
| 445 » » » if !unicode.IsLetter(c) && !unicode.IsDigit(c) { |
| 446 » » » » return false |
| 447 » » » } |
| 448 » » } |
| 449 » } |
| 450 » return true |
465 } | 451 } |
466 | 452 |
467 func fieldByIndex(v reflect.Value, index []int) reflect.Value { | 453 func fieldByIndex(v reflect.Value, index []int) reflect.Value { |
468 for _, i := range index { | 454 for _, i := range index { |
469 if v.Kind() == reflect.Ptr { | 455 if v.Kind() == reflect.Ptr { |
470 if v.IsNil() { | 456 if v.IsNil() { |
471 return reflect.Value{} | 457 return reflect.Value{} |
472 } | 458 } |
473 v = v.Elem() | 459 v = v.Elem() |
474 } | 460 } |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 } | 694 } |
709 | 695 |
710 fieldCache.Lock() | 696 fieldCache.Lock() |
711 if fieldCache.m == nil { | 697 if fieldCache.m == nil { |
712 fieldCache.m = map[reflect.Type][]field{} | 698 fieldCache.m = map[reflect.Type][]field{} |
713 } | 699 } |
714 fieldCache.m[t] = f | 700 fieldCache.m[t] = f |
715 fieldCache.Unlock() | 701 fieldCache.Unlock() |
716 return f | 702 return f |
717 } | 703 } |
LEFT | RIGHT |