summaryrefslogtreecommitdiff
path: root/src/pkg/json/struct.go
diff options
context:
space:
mode:
authorMichael Hoisie <hoisie@gmail.com>2009-11-19 20:45:03 -0800
committerMichael Hoisie <hoisie@gmail.com>2009-11-19 20:45:03 -0800
commita97dd86d35e662c7fb0aa5b7d471f5801a092148 (patch)
treed22fc921709218819f2626ffeb75c3bb2f5b842b /src/pkg/json/struct.go
parentdda9fcd01acd38e9cf35deb89a452c0fb80c6ddc (diff)
downloadgolang-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.go97
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))
+}