diff options
author | Sergei Skorobogatov <skorobo@rambler.ru> | 2010-02-22 14:32:40 -0800 |
---|---|---|
committer | Sergei Skorobogatov <skorobo@rambler.ru> | 2010-02-22 14:32:40 -0800 |
commit | c8a63ea5052d5e79d6144108f467bd6c4f613ea0 (patch) | |
tree | 338d886aeed248310b81ee2ab2e487ed48e8bb7e /src | |
parent | 8ae7258d8fa55e8565884d3ff89ee0ef85210786 (diff) | |
download | golang-c8a63ea5052d5e79d6144108f467bd6c4f613ea0.tar.gz |
json: fix quoted strings in Marshal
R=rsc
CC=golang-dev
http://codereview.appspot.com/217047
Committer: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/pkg/json/struct.go | 91 | ||||
-rw-r--r-- | src/pkg/json/struct_test.go | 23 |
2 files changed, 85 insertions, 29 deletions
diff --git a/src/pkg/json/struct.go b/src/pkg/json/struct.go index 955ec7c87..3357e04a3 100644 --- a/src/pkg/json/struct.go +++ b/src/pkg/json/struct.go @@ -317,76 +317,94 @@ type MarshalError struct { 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, "[") + +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 err + if err = writeValue(w, val.Elem(i)); err != nil { + return } if i < val.Len()-1 { - fmt.Fprint(w, ",") + if _, err = fmt.Fprint(w, ","); err != nil { + return + } } } - fmt.Fprint(w, "]") - return nil + _, err = fmt.Fprint(w, "]") + return } -func writeMap(w io.Writer, val *reflect.MapValue) os.Error { +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() - fmt.Fprint(w, "{") + if _, err = fmt.Fprint(w, "{"); err != nil { + return + } + for i := 0; i < len(keys); i++ { - fmt.Fprintf(w, "%q:", keys[i].(*reflect.StringValue).Get()) + 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 err + if err = writeValue(w, val.Elem(keys[i])); err != nil { + return } if i < len(keys)-1 { - fmt.Fprint(w, ",") + if _, err = fmt.Fprint(w, ","); err != nil { + return + } } } - fmt.Fprint(w, "}") - return nil + _, err = fmt.Fprint(w, "}") + return } -func writeStruct(w io.Writer, val *reflect.StructValue) os.Error { - fmt.Fprint(w, "{") +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) - fmt.Fprintf(w, "%q:", typ.Field(i).Name) - if err := writeValue(w, fieldValue); err != nil { - return err + 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 { - fmt.Fprint(w, ",") + if _, err = fmt.Fprint(w, ","); err != nil { + return + } } } - fmt.Fprint(w, "}") - return nil + _, err = fmt.Fprint(w, "}") + return } func writeValue(w io.Writer, val reflect.Value) (err os.Error) { if val == nil { - fmt.Fprint(w, "null") + _, err = fmt.Fprint(w, "null") return } switch v := val.(type) { case *reflect.StringValue: - fmt.Fprintf(w, "%q", v.Get()) + _, err = fmt.Fprint(w, Quote(v.Get())) case *reflect.ArrayValue: err = writeArrayOrSlice(w, v) case *reflect.SliceValue: @@ -396,27 +414,42 @@ func writeValue(w io.Writer, val reflect.Value) (err os.Error) { case *reflect.StructValue: err = writeStruct(w, v) case *reflect.ChanValue, - *reflect.UnsafePointerValue: + *reflect.UnsafePointerValue, + *reflect.FuncValue: err = &MarshalError{val.Type()} case *reflect.InterfaceValue: if v.IsNil() { - fmt.Fprint(w, "null") + _, err = fmt.Fprint(w, "null") } else { err = writeValue(w, v.Elem()) } case *reflect.PtrValue: if v.IsNil() { - fmt.Fprint(w, "null") + _, 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) - fmt.Fprint(w, value.Interface()) + _, err = fmt.Fprintf(w, "%#v", value.Interface()) } 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 { return writeValue(w, reflect.NewValue(val)) } diff --git a/src/pkg/json/struct_test.go b/src/pkg/json/struct_test.go index f1440c413..66d6e79c2 100644 --- a/src/pkg/json/struct_test.go +++ b/src/pkg/json/struct_test.go @@ -181,6 +181,18 @@ type OneField struct { a int } +type ScalarWithString int + +const ( + AA ScalarWithString = iota + BB + CC +) + +var scalarStrings = []string{"AA", "BB", "CC"} + +func (x ScalarWithString) String() string { return scalarStrings[x] } + var marshalTests = []marshalTest{ // basic string marshalTest{nil, "null"}, @@ -210,6 +222,17 @@ var marshalTests = []marshalTest{ marshalTest{map[string]*MTE{"hi": nil}, `{"hi":null}`}, marshalTest{map[string]interface{}{"hi": 3}, `{"hi":3}`}, marshalTest{&OneField{3}, `{"a":3}`}, + marshalTest{"\x05\x06", `"\u0005\u0006"`}, + marshalTest{uintptr(50000), "50000"}, + marshalTest{uint64(50000), "50000"}, + marshalTest{uint32(50000), "50000"}, + marshalTest{uint16(50000), "50000"}, + marshalTest{uint8(50), "50"}, + marshalTest{int64(50000), "50000"}, + marshalTest{int32(50000), "50000"}, + marshalTest{int16(10000), "10000"}, + marshalTest{int8(50), "50"}, + marshalTest{BB, "1"}, } func TestMarshal(t *testing.T) { |