mirror of
https://github.com/golang/go
synced 2024-11-25 15:17:58 -07:00
json: fix quoted strings in Marshal
R=rsc CC=golang-dev https://golang.org/cl/217047
This commit is contained in:
parent
f5b8124bd9
commit
7870672c7f
@ -317,76 +317,94 @@ type MarshalError struct {
|
|||||||
func (e *MarshalError) String() string {
|
func (e *MarshalError) String() string {
|
||||||
return "json cannot encode value of type " + e.T.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++ {
|
for i := 0; i < val.Len(); i++ {
|
||||||
if err := writeValue(w, val.Elem(i)); err != nil {
|
if err = writeValue(w, val.Elem(i)); err != nil {
|
||||||
return err
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if i < val.Len()-1 {
|
if i < val.Len()-1 {
|
||||||
fmt.Fprint(w, ",")
|
if _, err = fmt.Fprint(w, ","); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(w, "]")
|
_, err = fmt.Fprint(w, "]")
|
||||||
return nil
|
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()
|
key := val.Type().(*reflect.MapType).Key()
|
||||||
if _, ok := key.(*reflect.StringType); !ok {
|
if _, ok := key.(*reflect.StringType); !ok {
|
||||||
return &MarshalError{val.Type()}
|
return &MarshalError{val.Type()}
|
||||||
}
|
}
|
||||||
|
|
||||||
keys := val.Keys()
|
keys := val.Keys()
|
||||||
fmt.Fprint(w, "{")
|
if _, err = fmt.Fprint(w, "{"); err != nil {
|
||||||
for i := 0; i < len(keys); i++ {
|
return
|
||||||
fmt.Fprintf(w, "%q:", keys[i].(*reflect.StringValue).Get())
|
}
|
||||||
|
|
||||||
if err := writeValue(w, val.Elem(keys[i])); err != nil {
|
for i := 0; i < len(keys); i++ {
|
||||||
return err
|
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 i < len(keys)-1 {
|
||||||
fmt.Fprint(w, ",")
|
if _, err = fmt.Fprint(w, ","); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(w, "}")
|
_, err = fmt.Fprint(w, "}")
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeStruct(w io.Writer, val *reflect.StructValue) os.Error {
|
func writeStruct(w io.Writer, val *reflect.StructValue) (err os.Error) {
|
||||||
fmt.Fprint(w, "{")
|
if _, err = fmt.Fprint(w, "{"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
typ := val.Type().(*reflect.StructType)
|
typ := val.Type().(*reflect.StructType)
|
||||||
|
|
||||||
for i := 0; i < val.NumField(); i++ {
|
for i := 0; i < val.NumField(); i++ {
|
||||||
fieldValue := val.Field(i)
|
fieldValue := val.Field(i)
|
||||||
fmt.Fprintf(w, "%q:", typ.Field(i).Name)
|
if _, err = fmt.Fprintf(w, "%s:", Quote(typ.Field(i).Name)); err != nil {
|
||||||
if err := writeValue(w, fieldValue); err != nil {
|
return
|
||||||
return err
|
}
|
||||||
|
if err = writeValue(w, fieldValue); err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if i < val.NumField()-1 {
|
if i < val.NumField()-1 {
|
||||||
fmt.Fprint(w, ",")
|
if _, err = fmt.Fprint(w, ","); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprint(w, "}")
|
_, err = fmt.Fprint(w, "}")
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeValue(w io.Writer, val reflect.Value) (err os.Error) {
|
func writeValue(w io.Writer, val reflect.Value) (err os.Error) {
|
||||||
if val == nil {
|
if val == nil {
|
||||||
fmt.Fprint(w, "null")
|
_, err = fmt.Fprint(w, "null")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch v := val.(type) {
|
switch v := val.(type) {
|
||||||
case *reflect.StringValue:
|
case *reflect.StringValue:
|
||||||
fmt.Fprintf(w, "%q", v.Get())
|
_, err = fmt.Fprint(w, Quote(v.Get()))
|
||||||
case *reflect.ArrayValue:
|
case *reflect.ArrayValue:
|
||||||
err = writeArrayOrSlice(w, v)
|
err = writeArrayOrSlice(w, v)
|
||||||
case *reflect.SliceValue:
|
case *reflect.SliceValue:
|
||||||
@ -396,27 +414,42 @@ func writeValue(w io.Writer, val reflect.Value) (err os.Error) {
|
|||||||
case *reflect.StructValue:
|
case *reflect.StructValue:
|
||||||
err = writeStruct(w, v)
|
err = writeStruct(w, v)
|
||||||
case *reflect.ChanValue,
|
case *reflect.ChanValue,
|
||||||
*reflect.UnsafePointerValue:
|
*reflect.UnsafePointerValue,
|
||||||
|
*reflect.FuncValue:
|
||||||
err = &MarshalError{val.Type()}
|
err = &MarshalError{val.Type()}
|
||||||
case *reflect.InterfaceValue:
|
case *reflect.InterfaceValue:
|
||||||
if v.IsNil() {
|
if v.IsNil() {
|
||||||
fmt.Fprint(w, "null")
|
_, err = fmt.Fprint(w, "null")
|
||||||
} else {
|
} else {
|
||||||
err = writeValue(w, v.Elem())
|
err = writeValue(w, v.Elem())
|
||||||
}
|
}
|
||||||
case *reflect.PtrValue:
|
case *reflect.PtrValue:
|
||||||
if v.IsNil() {
|
if v.IsNil() {
|
||||||
fmt.Fprint(w, "null")
|
_, err = fmt.Fprint(w, "null")
|
||||||
} else {
|
} else {
|
||||||
err = writeValue(w, v.Elem())
|
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:
|
default:
|
||||||
value := val.(reflect.Value)
|
value := val.(reflect.Value)
|
||||||
fmt.Fprint(w, value.Interface())
|
_, err = fmt.Fprintf(w, "%#v", value.Interface())
|
||||||
}
|
}
|
||||||
return
|
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 {
|
func Marshal(w io.Writer, val interface{}) os.Error {
|
||||||
return writeValue(w, reflect.NewValue(val))
|
return writeValue(w, reflect.NewValue(val))
|
||||||
}
|
}
|
||||||
|
@ -181,6 +181,18 @@ type OneField struct {
|
|||||||
a int
|
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{
|
var marshalTests = []marshalTest{
|
||||||
// basic string
|
// basic string
|
||||||
marshalTest{nil, "null"},
|
marshalTest{nil, "null"},
|
||||||
@ -210,6 +222,17 @@ var marshalTests = []marshalTest{
|
|||||||
marshalTest{map[string]*MTE{"hi": nil}, `{"hi":null}`},
|
marshalTest{map[string]*MTE{"hi": nil}, `{"hi":null}`},
|
||||||
marshalTest{map[string]interface{}{"hi": 3}, `{"hi":3}`},
|
marshalTest{map[string]interface{}{"hi": 3}, `{"hi":3}`},
|
||||||
marshalTest{&OneField{3}, `{"a":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) {
|
func TestMarshal(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user