]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json: properly unmarshal empty arrays.
authorAndrey Mirtchovski <mirtchovski@gmail.com>
Wed, 30 Jan 2013 17:10:32 +0000 (09:10 -0800)
committerRuss Cox <rsc@golang.org>
Wed, 30 Jan 2013 17:10:32 +0000 (09:10 -0800)
The JSON unmarshaller failed to allocate an array when there
are no values for the input causing the `[]` unmarshalled
to []interface{} to generate []interface{}(nil) rather than
[]interface{}{}. This wasn't caught in the tests because Decode()
works correctly and because jsonBig never generated zero-sized
arrays. The modification to scanner_test.go quickly triggers
the error:

without the change to decoder.go, but with the change to scanner_test.go:

$ go test
--- FAIL: TestUnmarshalMarshal (0.10 seconds)
decode_test.go:446: Marshal jsonBig
scanner_test.go:206: diverge at 70: «03c1OL6$":null},{"[=» vs «03c1OL6$":[]},{"[=^\»
FAIL
exit status 1
FAIL encoding/json 0.266s

Also added a simple regression to decode_test.go.

R=adg, dave, rsc
CC=golang-dev
https://golang.org/cl/7196050

src/pkg/encoding/json/decode.go
src/pkg/encoding/json/decode_test.go
src/pkg/encoding/json/scanner_test.go

index 95e91209184aa8afd2eccb34115c7a64f3c0e4c9..e6e15b00d677c4ef076f7f2c637b889c795905ff 100644 (file)
@@ -742,7 +742,7 @@ func (d *decodeState) valueInterface() interface{} {
 
 // arrayInterface is like array but returns []interface{}.
 func (d *decodeState) arrayInterface() []interface{} {
-       var v []interface{}
+       var v = make([]interface{}, 0)
        for {
                // Look ahead for ] - can only happen on first iteration.
                op := d.scanWhile(scanSkipSpace)
index a91c6da01d3c1b3b90fb20f8b85b182158c2c01c..b65687e4a405cca2eba4612961c50dfd0308f2d4 100644 (file)
@@ -239,6 +239,12 @@ var unmarshalTests = []unmarshalTest{
        {in: `[1, 2, 3]`, ptr: new([1]int), out: [1]int{1}},
        {in: `[1, 2, 3]`, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}},
 
+       // empty array to interface test
+       {in: `[]`, ptr: new([]interface{}), out: []interface{}{}},
+       {in: `null`, ptr: new([]interface{}), out: []interface{}(nil)},
+       {in: `{"T":[]}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}},
+       {in: `{"T":null}`, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": interface{}(nil)}},
+
        // composite tests
        {in: allValueIndent, ptr: new(All), out: allValue},
        {in: allValueCompact, ptr: new(All), out: allValue},
index adb35715b9670ec65ea69261f06315204a1c1d8b..77d3455d3073747d663c3043a4e0b3d9a8f3bcab 100644 (file)
@@ -277,9 +277,6 @@ func genArray(n int) []interface{} {
        if f > n {
                f = n
        }
-       if n > 0 && f == 0 {
-               f = 1
-       }
        x := make([]interface{}, f)
        for i := range x {
                x[i] = genValue(((i+1)*n)/f - (i*n)/f)