diff options
Diffstat (limited to 'src/pkg/json/struct.go')
-rw-r--r-- | src/pkg/json/struct.go | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/src/pkg/json/struct.go b/src/pkg/json/struct.go index d94988b64..ab07d9339 100644 --- a/src/pkg/json/struct.go +++ b/src/pkg/json/struct.go @@ -224,7 +224,7 @@ func (b *structBuilder) Key(k string) Builder { } // Unmarshal parses the JSON syntax string s and fills in -// an arbitrary struct or array pointed at by val. +// an arbitrary struct or slice pointed at by val. // It uses the reflect package to assign to fields // and arrays embedded in val. Well-formed data that does not fit // into the struct is discarded. @@ -279,11 +279,27 @@ func (b *structBuilder) Key(k string) Builder { // assign to upper case fields. Unmarshal uses a case-insensitive // comparison to match JSON field names to struct field names. // +// To unmarshal a top-level JSON array, pass in a pointer to an empty +// slice of the correct type. +// // On success, Unmarshal returns with ok set to true. // On a syntax error, it returns with ok set to false and errtok // set to the offending token. func Unmarshal(s string, val interface{}) (ok bool, errtok string) { - b := &structBuilder{val: reflect.NewValue(val)}; + v := reflect.NewValue(val); + var b *structBuilder; + + // If val is a pointer to a slice, we mutate the pointee. + 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 |