Index: src/pkg/json/struct.go |
=================================================================== |
deleted file mode 100644 |
--- a/src/pkg/json/struct.go |
+++ /dev/null |
@@ -1,481 +0,0 @@ |
-// 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 ( |
- "bytes" |
- "fmt" |
- "io" |
- "os" |
- "reflect" |
- "strings" |
-) |
- |
-type structBuilder struct { |
- val reflect.Value |
- |
- // if map_ != nil, write val to map_[key] on each change |
- map_ *reflect.MapValue |
- key reflect.Value |
-} |
- |
-var nobuilder *structBuilder |
- |
-func isfloat(v reflect.Value) bool { |
- switch v.(type) { |
- case *reflect.FloatValue, *reflect.Float32Value, *reflect.Float64Value: |
- return true |
- } |
- return false |
-} |
- |
-func setfloat(v reflect.Value, f float64) { |
- switch v := v.(type) { |
- case *reflect.FloatValue: |
- v.Set(float(f)) |
- case *reflect.Float32Value: |
- v.Set(float32(f)) |
- case *reflect.Float64Value: |
- v.Set(float64(f)) |
- } |
-} |
- |
-func setint(v reflect.Value, i int64) { |
- switch v := v.(type) { |
- case *reflect.IntValue: |
- v.Set(int(i)) |
- case *reflect.Int8Value: |
- v.Set(int8(i)) |
- case *reflect.Int16Value: |
- v.Set(int16(i)) |
- case *reflect.Int32Value: |
- v.Set(int32(i)) |
- case *reflect.Int64Value: |
- v.Set(int64(i)) |
- case *reflect.UintValue: |
- v.Set(uint(i)) |
- case *reflect.Uint8Value: |
- v.Set(uint8(i)) |
- case *reflect.Uint16Value: |
- v.Set(uint16(i)) |
- case *reflect.Uint32Value: |
- v.Set(uint32(i)) |
- case *reflect.Uint64Value: |
- v.Set(uint64(i)) |
- } |
-} |
- |
-// If updating b.val is not enough to update the original, |
-// copy a changed b.val out to the original. |
-func (b *structBuilder) Flush() { |
- if b == nil { |
- return |
- } |
- if b.map_ != nil { |
- b.map_.SetElem(b.key, b.val) |
- } |
-} |
- |
-func (b *structBuilder) Int64(i int64) { |
- if b == nil { |
- return |
- } |
- v := b.val |
- if isfloat(v) { |
- setfloat(v, float64(i)) |
- } else { |
- setint(v, i) |
- } |
-} |
- |
-func (b *structBuilder) Uint64(i uint64) { |
- if b == nil { |
- return |
- } |
- v := b.val |
- if isfloat(v) { |
- setfloat(v, float64(i)) |
- } else { |
- setint(v, int64(i)) |
- } |
-} |
- |
-func (b *structBuilder) Float64(f float64) { |
- if b == nil { |
- return |
- } |
- v := b.val |
- if isfloat(v) { |
- setfloat(v, f) |
- } else { |
- setint(v, int64(f)) |
- } |
-} |
- |
-func (b *structBuilder) Null() {} |
- |
-func (b *structBuilder) String(s string) { |
- if b == nil { |
- return |
- } |
- if v, ok := b.val.(*reflect.StringValue); ok { |
- v.Set(s) |
- } |
-} |
- |
-func (b *structBuilder) Bool(tf bool) { |
- if b == nil { |
- return |
- } |
- if v, ok := b.val.(*reflect.BoolValue); ok { |
- v.Set(tf) |
- } |
-} |
- |
-func (b *structBuilder) Array() { |
- if b == nil { |
- return |
- } |
- if v, ok := b.val.(*reflect.SliceValue); ok { |
- if v.IsNil() { |
- v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8)) |
- } |
- } |
-} |
- |
-func (b *structBuilder) Elem(i int) Builder { |
- if b == nil || i < 0 { |
- return nobuilder |
- } |
- switch v := b.val.(type) { |
- case *reflect.ArrayValue: |
- if i < v.Len() { |
- return &structBuilder{val: v.Elem(i)} |
- } |
- case *reflect.SliceValue: |
- if i >= v.Cap() { |
- n := v.Cap() |
- if n < 8 { |
- n = 8 |
- } |
- for n <= i { |
- n *= 2 |
- } |
- nv := reflect.MakeSlice(v.Type().(*reflect.SliceType), v.Len(), n) |
- reflect.ArrayCopy(nv, v) |
- v.Set(nv) |
- } |
- if v.Len() <= i && i < v.Cap() { |
- v.SetLen(i + 1) |
- } |
- if i < v.Len() { |
- return &structBuilder{val: v.Elem(i)} |
- } |
- } |
- return nobuilder |
-} |
- |
-func (b *structBuilder) Map() { |
- if b == nil { |
- return |
- } |
- if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() { |
- if v.IsNil() { |
- v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem())) |
- b.Flush() |
- } |
- b.map_ = nil |
- b.val = v.Elem() |
- } |
- if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() { |
- v.Set(reflect.MakeMap(v.Type().(*reflect.MapType))) |
- } |
-} |
- |
-func (b *structBuilder) Key(k string) Builder { |
- if b == nil { |
- return nobuilder |
- } |
- switch v := reflect.Indirect(b.val).(type) { |
- case *reflect.StructValue: |
- t := v.Type().(*reflect.StructType) |
- // Case-insensitive field lookup. |
- k = strings.ToLower(k) |
- for i := 0; i < t.NumField(); i++ { |
- if strings.ToLower(t.Field(i).Name) == k { |
- return &structBuilder{val: v.Field(i)} |
- } |
- } |
- case *reflect.MapValue: |
- t := v.Type().(*reflect.MapType) |
- if t.Key() != reflect.Typeof(k) { |
- break |
- } |
- key := reflect.NewValue(k) |
- elem := v.Elem(key) |
- if elem == nil { |
- v.SetElem(key, reflect.MakeZero(t.Elem())) |
- elem = v.Elem(key) |
- } |
- return &structBuilder{val: elem, map_: v, key: key} |
- } |
- return nobuilder |
-} |
- |
-// Unmarshal parses the JSON syntax string s and fills in |
-// an arbitrary struct or slice pointed at by val. |
-// It uses the reflect package to assign to fields |
-// and arrays embedded in val. Well-formed data that does not fit |
-// into the struct is discarded. |
-// |
-// For example, given these definitions: |
-// |
-// type Email struct { |
-// Where string |
-// Addr string |
-// } |
-// |
-// type Result struct { |
-// Name string |
-// Phone string |
-// Email []Email |
-// } |
-// |
-// var r = Result{ "name", "phone", nil } |
-// |
-// unmarshalling the JSON syntax string |
-// |
-// { |
-// "email": [ |
-// { |
-// "where": "home", |
-// "addr": "gre@example.com" |
-// }, |
-// { |
-// "where": "work", |
-// "addr": "gre@work.com" |
-// } |
-// ], |
-// "name": "Grace R. Emlin", |
-// "address": "123 Main Street" |
-// } |
-// |
-// via Unmarshal(s, &r) is equivalent to assigning |
-// |
-// r = Result{ |
-// "Grace R. Emlin", // name |
-// "phone", // no phone given |
-// []Email{ |
-// Email{ "home", "gre@example.com" }, |
-// Email{ "work", "gre@work.com" }, |
-// }, |
-// } |
-// |
-// Note that the field r.Phone has not been modified and |
-// that the JSON field "address" was discarded. |
-// |
-// Because Unmarshal uses the reflect package, it can only |
-// assign to upper case fields. Unmarshal uses a case-insensitive |
-// comparison to match JSON field names to struct field names. |
-// |
-// To unmarshal a top-level JSON array, pass in a pointer to an empty |
-// slice of the correct type. |
-// |
-// On success, Unmarshal returns with ok set to true. |
-// On a syntax error, it returns with ok set to false and errtok |
-// set to the offending token. |
-func Unmarshal(s string, val interface{}) (ok bool, errtok string) { |
- v := reflect.NewValue(val) |
- var b *structBuilder |
- |
- // If val is a pointer to a slice, we append to the slice. |
- if ptr, ok := v.(*reflect.PtrValue); ok { |
- if slice, ok := ptr.Elem().(*reflect.SliceValue); ok { |
- b = &structBuilder{val: slice} |
- } |
- } |
- |
- if b == nil { |
- b = &structBuilder{val: v} |
- } |
- |
- ok, _, errtok = Parse(s, b) |
- if !ok { |
- return false, errtok |
- } |
- return true, "" |
-} |
- |
-type MarshalError struct { |
- T reflect.Type |
-} |
- |
-func (e *MarshalError) String() string { |
- return "json cannot encode value of type " + e.T.String() |
-} |
- |
-type writeState struct { |
- bytes.Buffer |
- indent string |
- newlines bool |
- depth int |
-} |
- |
-func (s *writeState) descend(bra byte) { |
- s.depth++ |
- s.WriteByte(bra) |
-} |
- |
-func (s *writeState) ascend(ket byte) { |
- s.depth-- |
- s.writeIndent() |
- s.WriteByte(ket) |
-} |
- |
-func (s *writeState) writeIndent() { |
- if s.newlines { |
- s.WriteByte('\n') |
- } |
- for i := 0; i < s.depth; i++ { |
- s.WriteString(s.indent) |
- } |
-} |
- |
-func (s *writeState) writeArrayOrSlice(val reflect.ArrayOrSliceValue) { |
- s.descend('[') |
- |
- for i := 0; i < val.Len(); i++ { |
- s.writeIndent() |
- s.writeValue(val.Elem(i)) |
- if i < val.Len()-1 { |
- s.WriteByte(',') |
- } |
- } |
- |
- s.ascend(']') |
-} |
- |
-func (s *writeState) writeMap(val *reflect.MapValue) { |
- key := val.Type().(*reflect.MapType).Key() |
- if _, ok := key.(*reflect.StringType); !ok { |
- panic(&MarshalError{val.Type()}) |
- } |
- |
- s.descend('{') |
- |
- keys := val.Keys() |
- for i := 0; i < len(keys); i++ { |
- s.writeIndent() |
- fmt.Fprintf(s, "%s:", Quote(keys[i].(*reflect.StringValue).Get())) |
- s.writeValue(val.Elem(keys[i])) |
- if i < len(keys)-1 { |
- s.WriteByte(',') |
- } |
- } |
- |
- s.ascend('}') |
-} |
- |
-func (s *writeState) writeStruct(val *reflect.StructValue) { |
- s.descend('{') |
- |
- typ := val.Type().(*reflect.StructType) |
- |
- for i := 0; i < val.NumField(); i++ { |
- s.writeIndent() |
- fmt.Fprintf(s, "%s:", Quote(typ.Field(i).Name)) |
- s.writeValue(val.Field(i)) |
- if i < val.NumField()-1 { |
- s.WriteByte(',') |
- } |
- } |
- |
- s.ascend('}') |
-} |
- |
-func (s *writeState) writeValue(val reflect.Value) { |
- if val == nil { |
- fmt.Fprint(s, "null") |
- return |
- } |
- |
- switch v := val.(type) { |
- case *reflect.StringValue: |
- fmt.Fprint(s, Quote(v.Get())) |
- case *reflect.ArrayValue: |
- s.writeArrayOrSlice(v) |
- case *reflect.SliceValue: |
- s.writeArrayOrSlice(v) |
- case *reflect.MapValue: |
- s.writeMap(v) |
- case *reflect.StructValue: |
- s.writeStruct(v) |
- case *reflect.ChanValue, |
- *reflect.UnsafePointerValue, |
- *reflect.FuncValue: |
- panic(&MarshalError{val.Type()}) |
- case *reflect.InterfaceValue: |
- if v.IsNil() { |
- fmt.Fprint(s, "null") |
- } else { |
- s.writeValue(v.Elem()) |
- } |
- case *reflect.PtrValue: |
- if v.IsNil() { |
- fmt.Fprint(s, "null") |
- } else { |
- s.writeValue(v.Elem()) |
- } |
- case *reflect.UintptrValue: |
- fmt.Fprintf(s, "%d", v.Get()) |
- case *reflect.Uint64Value: |
- fmt.Fprintf(s, "%d", v.Get()) |
- case *reflect.Uint32Value: |
- fmt.Fprintf(s, "%d", v.Get()) |
- case *reflect.Uint16Value: |
- fmt.Fprintf(s, "%d", v.Get()) |
- case *reflect.Uint8Value: |
- fmt.Fprintf(s, "%d", v.Get()) |
- default: |
- value := val.(reflect.Value) |
- fmt.Fprintf(s, "%#v", value.Interface()) |
- } |
-} |
- |
-func (s *writeState) marshal(w io.Writer, val interface{}) (err os.Error) { |
- defer func() { |
- if e := recover(); e != nil { |
- err = e.(*MarshalError) |
- } |
- }() |
- s.writeValue(reflect.NewValue(val)) |
- if s.newlines { |
- s.WriteByte('\n') |
- } |
- _, err = s.WriteTo(w) |
- return |
-} |
- |
-// Marshal writes the JSON encoding of val to w. |
-// |
-// Due to limitations in JSON, val cannot include cyclic data |
-// structures, channels, functions, or maps. |
-func Marshal(w io.Writer, val interface{}) os.Error { |
- s := &writeState{indent: "", newlines: false, depth: 0} |
- return s.marshal(w, val) |
-} |
- |
-// MarshalIndent writes the JSON encoding of val to w, |
-// indenting nested values using the indent string. |
-// |
-// Due to limitations in JSON, val cannot include cyclic data |
-// structures, channels, functions, or maps. |
-func MarshalIndent(w io.Writer, val interface{}, indent string) os.Error { |
- s := &writeState{indent: indent, newlines: true, depth: 0} |
- return s.marshal(w, val) |
-} |