// 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) (err os.Error) { s.descend('[') for i := 0; i < val.Len(); i++ { s.writeIndent() if err = s.writeValue(val.Elem(i)); err != nil { return } if i < val.Len()-1 { s.WriteByte(',') } } s.ascend(']') return } func (s *writeState) writeMap(val *reflect.MapValue) (err os.Error) { key := val.Type().(*reflect.MapType).Key() if _, ok := key.(*reflect.StringType); !ok { return &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())) if err = s.writeValue(val.Elem(keys[i])); err != nil { return } if i < len(keys)-1 { s.WriteByte(',') } } s.ascend('}') return } func (s *writeState) writeStruct(val *reflect.StructValue) (err os.Error) { s.descend('{') typ := val.Type().(*reflect.StructType) for i := 0; i < val.NumField(); i++ { s.writeIndent() fieldValue := val.Field(i) fmt.Fprintf(s, "%s:", Quote(typ.Field(i).Name)) if err = s.writeValue(fieldValue); err != nil { return } if i < val.NumField()-1 { s.WriteByte(',') } } s.ascend('}') return } func (s *writeState) writeValue(val reflect.Value) (err os.Error) { if val == nil { fmt.Fprint(s, "null") return } switch v := val.(type) { case *reflect.StringValue: fmt.Fprint(s, Quote(v.Get())) case *reflect.ArrayValue: err = s.writeArrayOrSlice(v) case *reflect.SliceValue: err = s.writeArrayOrSlice(v) case *reflect.MapValue: err = s.writeMap(v) case *reflect.StructValue: err = s.writeStruct(v) case *reflect.ChanValue, *reflect.UnsafePointerValue, *reflect.FuncValue: err = &MarshalError{val.Type()} case *reflect.InterfaceValue: if v.IsNil() { fmt.Fprint(s, "null") } else { err = s.writeValue(v.Elem()) } case *reflect.PtrValue: if v.IsNil() { fmt.Fprint(s, "null") } else { err = 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()) } return } func (s *writeState) marshal(w io.Writer, val interface{}) (err os.Error) { err = s.writeValue(reflect.NewValue(val)) if err != nil { return } 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) }