| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Marshalling and unmarshalling of |
| // JSON data into Go structs using reflection. |
| |
| package json |
| |
| import ( |
| "json"; |
| "reflect"; |
| ) |
| |
| type _StructBuilder struct { |
| val reflect.Value |
| } |
| |
| var nobuilder *_StructBuilder |
| |
| func setfloat(v reflect.Value, f float64) { |
| switch v.Kind() { |
| case reflect.FloatKind: |
| v.(reflect.FloatValue).Set(float(f)); |
| case reflect.Float32Kind: |
| v.(reflect.Float32Value).Set(float32(f)); |
| case reflect.Float64Kind: |
| v.(reflect.Float64Value).Set(float64(f)); |
| } |
| } |
| |
| func setint(v reflect.Value, i int64) { |
| switch v.Kind() { |
| case reflect.IntKind: |
| v.(reflect.IntValue).Set(int(i)); |
| case reflect.Int8Kind: |
| v.(reflect.Int8Value).Set(int8(i)); |
| case reflect.Int16Kind: |
| v.(reflect.Int16Value).Set(int16(i)); |
| case reflect.Int32Kind: |
| v.(reflect.Int32Value).Set(int32(i)); |
| case reflect.Int64Kind: |
| v.(reflect.Int64Value).Set(int64(i)); |
| case reflect.UintKind: |
| v.(reflect.UintValue).Set(uint(i)); |
| case reflect.Uint8Kind: |
| v.(reflect.Uint8Value).Set(uint8(i)); |
| case reflect.Uint16Kind: |
| v.(reflect.Uint16Value).Set(uint16(i)); |
| case reflect.Uint32Kind: |
| v.(reflect.Uint32Value).Set(uint32(i)); |
| case reflect.Uint64Kind: |
| v.(reflect.Uint64Value).Set(uint64(i)); |
| } |
| } |
| |
| func (b *_StructBuilder) Int64(i int64) { |
| if b == nil { |
| return |
| } |
| v := b.val; |
| switch v.Kind() { |
| case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind: |
| setfloat(v, float64(i)); |
| default: |
| setint(v, i); |
| } |
| } |
| |
| func (b *_StructBuilder) Uint64(i uint64) { |
| if b == nil { |
| return |
| } |
| v := b.val; |
| switch v.Kind() { |
| case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind: |
| setfloat(v, float64(i)); |
| default: |
| setint(v, int64(i)); |
| } |
| } |
| |
| func (b *_StructBuilder) Float64(f float64) { |
| if b == nil { |
| return |
| } |
| v := b.val; |
| switch v.Kind() { |
| case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind: |
| setfloat(v, f); |
| default: |
| setint(v, int64(f)); |
| } |
| } |
| |
| func (b *_StructBuilder) Null() { |
| } |
| |
| func (b *_StructBuilder) String(s string) { |
| if b == nil { |
| return |
| } |
| if v := b.val; v.Kind() == reflect.StringKind { |
| v.(reflect.StringValue).Set(s); |
| } |
| } |
| |
| func (b *_StructBuilder) Bool(tf bool) { |
| if b == nil { |
| return |
| } |
| if v := b.val; v.Kind() == reflect.BoolKind { |
| v.(reflect.BoolValue).Set(tf); |
| } |
| } |
| |
| func (b *_StructBuilder) Array() { |
| if b == nil { |
| return |
| } |
| if v := b.val; v.Kind() == reflect.PtrKind { |
| pv := v.(reflect.PtrValue); |
| psubtype := pv.Type().(reflect.PtrType).Sub(); |
| if pv.Get() == nil && psubtype.Kind() == reflect.ArrayKind { |
| av := reflect.NewSliceValue(psubtype.(reflect.ArrayType), 0, 8); |
| pv.SetSub(av); |
| } |
| } |
| } |
| |
| func (b *_StructBuilder) Elem(i int) Builder { |
| if b == nil || i < 0 { |
| return nobuilder |
| } |
| v := b.val; |
| if v.Kind() == reflect.PtrKind { |
| // If we have a pointer to an array, allocate or grow |
| // the array as necessary. Then set v to the array itself. |
| pv := v.(reflect.PtrValue); |
| psub := pv.Sub(); |
| if psub.Kind() == reflect.ArrayKind { |
| av := psub.(reflect.ArrayValue); |
| if i > av.Cap() { |
| n := av.Cap(); |
| if n < 8 { |
| n = 8 |
| } |
| for n <= i { |
| n *= 2 |
| } |
| av1 := reflect.NewSliceValue(av.Type().(reflect.ArrayType), av.Len(), n); |
| av1.CopyFrom(av, av.Len()); |
| pv.SetSub(av1); |
| av = av1; |
| } |
| } |
| v = psub; |
| } |
| if v.Kind() == reflect.ArrayKind { |
| // Array was grown above, or is fixed size. |
| av := v.(reflect.ArrayValue); |
| if av.Len() <= i && i < av.Cap() { |
| av.SetLen(i+1); |
| } |
| if i < av.Len() { |
| return &_StructBuilder( av.Elem(i) ) |
| } |
| } |
| return nobuilder |
| } |
| |
| func (b *_StructBuilder) Map() { |
| if b == nil { |
| return |
| } |
| if v := b.val; v.Kind() == reflect.PtrKind { |
| pv := v.(reflect.PtrValue); |
| if pv.Get() == nil { |
| pv.SetSub(reflect.NewInitValue(pv.Type().(reflect.PtrType).Sub())) |
| } |
| } |
| } |
| |
| func (b *_StructBuilder) Key(k string) Builder { |
| if b == nil { |
| return nobuilder |
| } |
| v := b.val; |
| if v.Kind() == reflect.PtrKind { |
| v = v.(reflect.PtrValue).Sub(); |
| } |
| if v.Kind() == reflect.StructKind { |
| sv := v.(reflect.StructValue); |
| t := v.Type().(reflect.StructType); |
| for i := 0; i < t.Len(); i++ { |
| name, typ, tag, off := t.Field(i); |
| if k == name { |
| return &_StructBuilder( sv.Field(i) ) |
| } |
| } |
| } |
| return nobuilder |
| } |
| |
| func Unmarshal(s string, val interface{}) (ok bool, errtok string) { |
| var errindx int; |
| var val1 interface{}; |
| b := &_StructBuilder( reflect.NewValue(val) ); |
| ok, errindx, errtok = Parse(s, b); |
| if !ok { |
| return false, errtok |
| } |
| return true, "" |
| } |