LEFT | RIGHT |
(no file at all) | |
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 // Represents JSON data structure using native Go types: booleans, floats, | 5 // Represents JSON data structure using native Go types: booleans, floats, |
6 // strings, arrays, and maps. | 6 // strings, arrays, and maps. |
7 | 7 |
8 package json | 8 package json |
9 | 9 |
10 import ( | 10 import ( |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 | 486 |
487 if mv.IsValid() { | 487 if mv.IsValid() { |
488 elemType := mv.Type().Elem() | 488 elemType := mv.Type().Elem() |
489 if !mapElem.IsValid() { | 489 if !mapElem.IsValid() { |
490 mapElem = reflect.New(elemType).Elem() | 490 mapElem = reflect.New(elemType).Elem() |
491 } else { | 491 } else { |
492 mapElem.Set(reflect.Zero(elemType)) | 492 mapElem.Set(reflect.Zero(elemType)) |
493 } | 493 } |
494 subv = mapElem | 494 subv = mapElem |
495 } else { | 495 } else { |
496 » » » var f reflect.StructField | 496 » » » var f *field |
497 » » » var ok bool | 497 » » » fields := cachedTypeFields(sv.Type()) |
498 » » » st := sv.Type() | 498 » » » for i := range fields { |
499 » » » for i := 0; i < sv.NumField(); i++ { | 499 » » » » ff := &fields[i] |
500 » » » » sf := st.Field(i) | 500 » » » » if ff.name == key { |
501 » » » » tag := sf.Tag.Get("json") | 501 » » » » » f = ff |
502 » » » » if tag == "-" { | 502 » » » » » break |
503 » » » » » // Pretend this field doesn't exist. | |
504 » » » » » continue | |
505 } | 503 } |
506 » » » » if sf.Anonymous { | 504 » » » » if f == nil && strings.EqualFold(ff.name, key) { |
507 » » » » » // Pretend this field doesn't exist, | 505 » » » » » f = ff |
508 » » » » » // so that we can do a good job with | |
509 » » » » » // these in a later version. | |
510 » » » » » continue | |
511 } | 506 } |
512 » » » » // First, tag match | 507 » » » } |
513 » » » » tagName, _ := parseTag(tag) | 508 » » » if f != nil { |
514 » » » » if tagName != "" { | 509 » » » » subv = sv |
515 » » » » » if tagName == key { | 510 » » » » destring = f.quoted |
516 » » » » » » f = sf | 511 » » » » for _, i := range f.index { |
517 » » » » » » ok = true | 512 » » » » » if subv.Kind() == reflect.Ptr { |
518 » » » » » » break // no better match possibl
e | 513 » » » » » » if subv.IsNil() { |
| 514 » » » » » » » subv.Set(reflect.New(sub
v.Type().Elem())) |
| 515 » » » » » » } |
| 516 » » » » » » subv = subv.Elem() |
519 } | 517 } |
520 » » » » » // There was a tag, but it didn't match. | 518 » » » » » subv = subv.Field(i) |
521 » » » » » // Ignore field names. | |
522 » » » » » continue | |
523 } | 519 } |
524 » » » » // Second, exact field name match | 520 » » » } else { |
525 » » » » if sf.Name == key { | 521 » » » » // To give a good error, a quick scan for unexpo
rted fields in top level. |
526 » » » » » f = sf | 522 » » » » st := sv.Type() |
527 » » » » » ok = true | 523 » » » » for i := 0; i < st.NumField(); i++ { |
| 524 » » » » » f := st.Field(i) |
| 525 » » » » » if f.PkgPath != "" && strings.EqualFold(
f.Name, key) { |
| 526 » » » » » » d.saveError(&UnmarshalFieldError
{key, st, f}) |
| 527 » » » » » } |
528 } | 528 } |
529 // Third, case-insensitive field name match, | |
530 // but only if a better match hasn't already bee
n seen | |
531 if !ok && strings.EqualFold(sf.Name, key) { | |
532 f = sf | |
533 ok = true | |
534 } | |
535 } | |
536 | |
537 // Extract value; name must be exported. | |
538 if ok { | |
539 if f.PkgPath != "" { | |
540 d.saveError(&UnmarshalFieldError{key, st
, f}) | |
541 } else { | |
542 subv = sv.FieldByIndex(f.Index) | |
543 } | |
544 _, opts := parseTag(f.Tag.Get("json")) | |
545 destring = opts.Contains("string") | |
546 } | 529 } |
547 } | 530 } |
548 | 531 |
549 // Read : before value. | 532 // Read : before value. |
550 if op == scanSkipSpace { | 533 if op == scanSkipSpace { |
551 op = d.scanWhile(scanSkipSpace) | 534 op = d.scanWhile(scanSkipSpace) |
552 } | 535 } |
553 if op != scanObjectKey { | 536 if op != scanObjectKey { |
554 d.error(errPhase) | 537 d.error(errPhase) |
555 } | 538 } |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 | 981 |
999 // Coerce to well-formed UTF-8. | 982 // Coerce to well-formed UTF-8. |
1000 default: | 983 default: |
1001 rr, size := utf8.DecodeRune(s[r:]) | 984 rr, size := utf8.DecodeRune(s[r:]) |
1002 r += size | 985 r += size |
1003 w += utf8.EncodeRune(b[w:], rr) | 986 w += utf8.EncodeRune(b[w:], rr) |
1004 } | 987 } |
1005 } | 988 } |
1006 return b[0:w], true | 989 return b[0:w], true |
1007 } | 990 } |
1008 | |
1009 // The following is issue 3069. | |
1010 | |
1011 // BUG(rsc): This package ignores anonymous (embedded) struct fields | |
1012 // during encoding and decoding. A future version may assign meaning | |
1013 // to them. To force an anonymous field to be ignored in all future | |
1014 // versions of this package, use an explicit `json:"-"` tag in the struct | |
1015 // definition. | |
LEFT | RIGHT |