diff options
| author | Michael Hoisie <hoisie@gmail.com> | 2009-11-19 20:45:03 -0800 | 
|---|---|---|
| committer | Michael Hoisie <hoisie@gmail.com> | 2009-11-19 20:45:03 -0800 | 
| commit | a97dd86d35e662c7fb0aa5b7d471f5801a092148 (patch) | |
| tree | d22fc921709218819f2626ffeb75c3bb2f5b842b /src/pkg/json/struct.go | |
| parent | dda9fcd01acd38e9cf35deb89a452c0fb80c6ddc (diff) | |
| download | golang-a97dd86d35e662c7fb0aa5b7d471f5801a092148.tar.gz | |
Add json.Marshal to json package
R=rsc
CC=golang-dev
http://codereview.appspot.com/157068
Committer: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/pkg/json/struct.go')
| -rw-r--r-- | src/pkg/json/struct.go | 97 | 
1 files changed, 97 insertions, 0 deletions
| diff --git a/src/pkg/json/struct.go b/src/pkg/json/struct.go index 4e560ec86..6b74cdae0 100644 --- a/src/pkg/json/struct.go +++ b/src/pkg/json/struct.go @@ -8,6 +8,9 @@  package json  import ( +	"fmt"; +	"io"; +	"os";  	"reflect";  	"strings";  ) @@ -306,3 +309,97 @@ func Unmarshal(s string, val interface{}) (ok bool, errtok string) {  	}  	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) os.Error { +	fmt.Fprint(w, "["); + +	for i := 0; i < val.Len(); i++ { +		if err := writeValue(w, val.Elem(i)); err != nil { +			return err +		} + +		if i < val.Len()-1 { +			fmt.Fprint(w, ",") +		} +	} + +	fmt.Fprint(w, "]"); +	return nil; +} + +func writeMap(w io.Writer, val *reflect.MapValue) os.Error { +	key := val.Type().(*reflect.MapType).Key(); +	if _, ok := key.(*reflect.StringType); !ok { +		return &MarshalError{val.Type()} +	} + +	keys := val.Keys(); +	fmt.Fprint(w, "{"); +	for i := 0; i < len(keys); i++ { +		fmt.Fprintf(w, "%q:", keys[i].(*reflect.StringValue).Get()); + +		if err := writeValue(w, val.Elem(keys[i])); err != nil { +			return err +		} + +		if i < len(keys)-1 { +			fmt.Fprint(w, ",") +		} +	} + +	fmt.Fprint(w, "}"); +	return nil; +} + +func writeStruct(w io.Writer, val *reflect.StructValue) os.Error { +	fmt.Fprint(w, "{"); + +	typ := val.Type().(*reflect.StructType); + +	for i := 0; i < val.NumField(); i++ { +		fieldValue := val.Field(i); +		fmt.Fprintf(w, "%q:", typ.Field(i).Name); +		writeValue(w, fieldValue); +		if i < val.NumField()-1 { +			fmt.Fprint(w, ",") +		} +	} + +	fmt.Fprint(w, "}"); +	return nil; +} + +func writeValue(w io.Writer, val reflect.Value) (err os.Error) { +	switch v := val.(type) { +	case *reflect.StringValue: +		fmt.Fprintf(w, "%q", 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.InterfaceValue, +		*reflect.PtrValue, +		*reflect.UnsafePointerValue: +		return &MarshalError{val.Type()} +	default: +		value := val.(reflect.Value); +		fmt.Fprint(w, value.Interface()); +	} +	return nil; +} + +func Marshal(w io.Writer, val interface{}) os.Error { +	return writeValue(w, reflect.NewValue(val)) +} | 
