]> Cypherpunks repositories - gostls13.git/commitdiff
json: allow one to unmarshal a top-level JSON array.
authorAdam Langley <agl@golang.org>
Fri, 13 Nov 2009 21:00:45 +0000 (13:00 -0800)
committerAdam Langley <agl@golang.org>
Fri, 13 Nov 2009 21:00:45 +0000 (13:00 -0800)
Fixies issue 114.

R=rsc
CC=golang-dev
https://golang.org/cl/154121

src/pkg/json/struct.go
src/pkg/json/struct_test.go

index d94988b6470b299c7ca2342529192e012ff8eaa3..ab07d93399d1abb029114c40a7b92588c0928cd3 100644 (file)
@@ -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
index 15446961a8cc871fde96e286eb1b68c3ae73e4fe..89d363d9ee15e749eb7bce8dd58d36d710b85d44 100644 (file)
@@ -126,9 +126,34 @@ func TestIssue147(t *testing.T) {
        var timeline Issue147;
        Unmarshal(issue147Input, &timeline);
 
+       if len(timeline.Test) != 30 {
+               t.Errorf("wrong length: got %d want 30", len(timeline.Test))
+       }
+
        for i, e := range timeline.Test {
                if e.Text != strconv.Itoa(i) {
                        t.Errorf("index: %d got: %s want: %d", i, e.Text, i)
                }
        }
 }
+
+type Issue114 struct {
+       Text string;
+}
+
+const issue114Input = `[{"text" : "0"}, {"text" : "1"}, {"text" : "2"}, {"text" : "3"}]`
+
+func TestIssue114(t *testing.T) {
+       var items []Issue114;
+       Unmarshal(issue114Input, &items);
+
+       if len(items) != 4 {
+               t.Errorf("wrong length: got %d want 4", len(items))
+       }
+
+       for i, e := range items {
+               if e.Text != strconv.Itoa(i) {
+                       t.Errorf("index: %d got: %s want: %d", i, e.Text, i)
+               }
+       }
+}