diff options
author | Adam Langley <agl@golang.org> | 2009-11-13 13:00:45 -0800 |
---|---|---|
committer | Adam Langley <agl@golang.org> | 2009-11-13 13:00:45 -0800 |
commit | d04a510fa310c6d5fa8b6a3dec07e88f0b998dd6 (patch) | |
tree | 98bf497be1f78e90b0e0547d7e1f5f994d8546ec /src/pkg/json/struct.go | |
parent | 23abe19ca16ba0939ec537d950f2315a6122ad43 (diff) | |
download | golang-d04a510fa310c6d5fa8b6a3dec07e88f0b998dd6.tar.gz |
json: allow one to unmarshal a top-level JSON array.
Fixies issue 114.
R=rsc
CC=golang-dev
http://codereview.appspot.com/154121
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 |