package json
import (
"fmt"
"io"
"os"
"reflect"
"strings"
)
type structBuilder struct {
val reflect.Value
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))
}
}
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)
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
}
func Unmarshal(s string, val interface{}) (ok bool, errtok string) {
v := reflect.NewValue(val)
var b *structBuilder
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()
}
func writeArrayOrSlice(w io.Writer, val reflect.ArrayOrSliceValue) (err os.Error) {
if _, err = fmt.Fprint(w, "["); err != nil {
return
}
for i := 0; i < val.Len(); i++ {
if err = writeValue(w, val.Elem(i)); err != nil {
return
}
if i < val.Len()-1 {
if _, err = fmt.Fprint(w, ","); err != nil {
return
}
}
}
_, err = fmt.Fprint(w, "]")
return
}
func writeMap(w io.Writer, val *reflect.MapValue) (err os.Error) {
key := val.Type().(*reflect.MapType).Key()
if _, ok := key.(*reflect.StringType); !ok {
return &MarshalError{val.Type()}
}
keys := val.Keys()
if _, err = fmt.Fprint(w, "{"); err != nil {
return
}
for i := 0; i < len(keys); i++ {
if _, err = fmt.Fprintf(w, "%s:", Quote(keys[i].(*reflect.StringValue).Get())); err != nil {
return
}
if err = writeValue(w, val.Elem(keys[i])); err != nil {
return
}
if i < len(keys)-1 {
if _, err = fmt.Fprint(w, ","); err != nil {
return
}
}
}
_, err = fmt.Fprint(w, "}")
return
}
func writeStruct(w io.Writer, val *reflect.StructValue) (err os.Error) {
if _, err = fmt.Fprint(w, "{"); err != nil {
return
}
typ := val.Type().(*reflect.StructType)
for i := 0; i < val.NumField(); i++ {
fieldValue := val.Field(i)
if _, err = fmt.Fprintf(w, "%s:", Quote(typ.Field(i).Name)); err != nil {
return
}
if err = writeValue(w, fieldValue); err != nil {
return
}
if i < val.NumField()-1 {
if _, err = fmt.Fprint(w, ","); err != nil {
return
}
}
}
_, err = fmt.Fprint(w, "}")
return
}
func writeValue(w io.Writer, val reflect.Value) (err os.Error) {
if val == nil {
_, err = fmt.Fprint(w, "null")
return
}
switch v := val.(type) {
case *reflect.StringValue:
_, err = fmt.Fprint(w, Quote(v.Get()))
case *reflect.ArrayValue:
err = writeArrayOrSlice(w, v)
case *reflect.SliceValue:
err = writeArrayOrSlice(w, v)
case *reflect.MapValue:
err = writeMap(w, v)
case *reflect.StructValue:
err = writeStruct(w, v)
case *reflect.ChanValue,
*reflect.UnsafePointerValue,
*reflect.FuncValue:
err = &MarshalError{val.Type()}
case *reflect.InterfaceValue:
if v.IsNil() {
_, err = fmt.Fprint(w, "null")
} else {
err = writeValue(w, v.Elem())
}
case *reflect.PtrValue:
if v.IsNil() {
_, err = fmt.Fprint(w, "null")
} else {
err = writeValue(w, v.Elem())
}
case *reflect.UintptrValue:
_, err = fmt.Fprintf(w, "%d", v.Get())
case *reflect.Uint64Value:
_, err = fmt.Fprintf(w, "%d", v.Get())
case *reflect.Uint32Value:
_, err = fmt.Fprintf(w, "%d", v.Get())
case *reflect.Uint16Value:
_, err = fmt.Fprintf(w, "%d", v.Get())
case *reflect.Uint8Value:
_, err = fmt.Fprintf(w, "%d", v.Get())
default:
value := val.(reflect.Value)
_, err = fmt.Fprintf(w, "%#v", value.Interface())
}
return
}
func Marshal(w io.Writer, val interface{}) os.Error {
return writeValue(w, reflect.NewValue(val))
}