gojay

high performance JSON encoder/decoder with stream API for Golang
git clone git://git.lair.cx/gojay
Log | Files | Refs | README | LICENSE

decode_array_test.go (19720B)


      1 package gojay
      2 
      3 import (
      4 	"strings"
      5 	"testing"
      6 
      7 	"github.com/stretchr/testify/assert"
      8 )
      9 
     10 type testSliceInts []int
     11 
     12 func (t *testSliceInts) UnmarshalJSONArray(dec *Decoder) error {
     13 	i := 0
     14 	if err := dec.AddInt(&i); err != nil {
     15 		return err
     16 	}
     17 	*t = append(*t, i)
     18 	return nil
     19 }
     20 
     21 func TestSliceInts(t *testing.T) {
     22 	testCases := []struct {
     23 		name           string
     24 		json           string
     25 		expectedResult testSliceInts
     26 		err            bool
     27 		errType        interface{}
     28 	}{
     29 		{
     30 			name:           "basic-test",
     31 			json:           "[1,2,3,43567788543,45777655,432,0]",
     32 			expectedResult: testSliceInts{1, 2, 3, 43567788543, 45777655, 432, 0},
     33 		},
     34 		{
     35 			name:           "basic-test",
     36 			json:           "[1,2,3,43567788543,null,432,0]",
     37 			expectedResult: testSliceInts{1, 2, 3, 43567788543, 0, 432, 0},
     38 		},
     39 		{
     40 			name:           "empty",
     41 			json:           "[]",
     42 			expectedResult: testSliceInts{},
     43 		},
     44 		{
     45 			name:           "invalid-json",
     46 			json:           "[",
     47 			expectedResult: testSliceInts{},
     48 			err:            true,
     49 		},
     50 		{
     51 			name:           "floats",
     52 			json:           "[1,2,3,43567788543,457.7765,432,0,0.45]",
     53 			expectedResult: testSliceInts{1, 2, 3, 43567788543, 457, 432, 0, 0},
     54 		},
     55 		{
     56 			name:           "invalid-type",
     57 			json:           `[1,2,3,43567788543,457.7765,432,0,"test"]`,
     58 			expectedResult: testSliceInts{1, 2, 3, 43567788543, 457, 432, 0, 0},
     59 			err:            true,
     60 			errType:        InvalidUnmarshalError(""),
     61 		},
     62 		{
     63 			name:           "invalid-json",
     64 			json:           `[1,2,3",43567788543,457.7765,432,0,"test"]`,
     65 			expectedResult: testSliceInts{1, 2, 3, 43567788543, 457, 432, 0, 0},
     66 			err:            true,
     67 			errType:        InvalidJSONError(""),
     68 		},
     69 	}
     70 
     71 	for _, testCase := range testCases {
     72 		s := make(testSliceInts, 0)
     73 		dec := BorrowDecoder(strings.NewReader(testCase.json))
     74 		defer dec.Release()
     75 		err := dec.Decode(&s)
     76 		if testCase.err {
     77 			assert.NotNil(t, err, "err should not be nil")
     78 			if testCase.errType != nil {
     79 				assert.IsType(t, testCase.errType, err, "err should be of the given type")
     80 			}
     81 			continue
     82 		}
     83 		for k, v := range testCase.expectedResult {
     84 			assert.Equal(t, v, s[k], "value at given index should be the same as expected results")
     85 		}
     86 	}
     87 }
     88 
     89 type testSliceStrings []string
     90 
     91 func (t *testSliceStrings) UnmarshalJSONArray(dec *Decoder) error {
     92 	str := ""
     93 	if err := dec.AddString(&str); err != nil {
     94 		return err
     95 	}
     96 	*t = append(*t, str)
     97 	return nil
     98 }
     99 
    100 func TestSliceStrings(t *testing.T) {
    101 	testCases := []struct {
    102 		name           string
    103 		json           string
    104 		expectedResult testSliceStrings
    105 		err            bool
    106 		errType        interface{}
    107 	}{
    108 		{
    109 			name:           "basic-test",
    110 			json:           `["hello world", "hey" , "foo","bar"]`,
    111 			expectedResult: testSliceStrings{"hello world", "hey", "foo", "bar"},
    112 		},
    113 		{
    114 			name:           "basic-test",
    115 			json:           `["hello world", "hey" , "foo","bar \n escape"]`,
    116 			expectedResult: testSliceStrings{"hello world", "hey", "foo", "bar \n escape"},
    117 		},
    118 		{
    119 			name:           "basic-test",
    120 			json:           `["hello world", "hey" , null,"bar \n escape"]`,
    121 			expectedResult: testSliceStrings{"hello world", "hey", "", "bar \n escape"},
    122 		},
    123 		{
    124 			name:           "invalid-type",
    125 			json:           `["foo",1,2,3,"test"]`,
    126 			expectedResult: testSliceStrings{},
    127 			err:            true,
    128 			errType:        InvalidUnmarshalError(""),
    129 		},
    130 		{
    131 			name:           "invalid-json",
    132 			json:           `["hello world]`,
    133 			expectedResult: testSliceStrings{},
    134 			err:            true,
    135 			errType:        InvalidJSONError(""),
    136 		},
    137 	}
    138 
    139 	for _, testCase := range testCases {
    140 		t.Run(testCase.name, func(t *testing.T) {
    141 			s := make(testSliceStrings, 0)
    142 			dec := BorrowDecoder(strings.NewReader(testCase.json))
    143 			defer dec.Release()
    144 			err := dec.Decode(&s)
    145 			if testCase.err {
    146 				assert.NotNil(t, err, "err should not be nil")
    147 				if testCase.errType != nil {
    148 					assert.IsType(t, testCase.errType, err, "err should be of the given type")
    149 				}
    150 				return
    151 			}
    152 			assert.Nil(t, err, "err should be nil")
    153 			for k, v := range testCase.expectedResult {
    154 				assert.Equal(t, v, s[k], "value at given index should be the same as expected results")
    155 			}
    156 		})
    157 	}
    158 }
    159 
    160 type testSliceBools []bool
    161 
    162 func (t *testSliceBools) UnmarshalJSONArray(dec *Decoder) error {
    163 	b := false
    164 	if err := dec.AddBool(&b); err != nil {
    165 		return err
    166 	}
    167 	*t = append(*t, b)
    168 	return nil
    169 }
    170 
    171 func TestSliceBools(t *testing.T) {
    172 	testCases := []struct {
    173 		name           string
    174 		json           string
    175 		expectedResult testSliceBools
    176 		err            bool
    177 		errType        interface{}
    178 	}{
    179 		{
    180 			name:           "basic-test",
    181 			json:           `[true, false, false, true, true, false]`,
    182 			expectedResult: testSliceBools{true, false, false, true, true, false},
    183 		},
    184 		{
    185 			name:           "basic-test2",
    186 			json:           `[true, false, false, true, null,null,true,false]`,
    187 			expectedResult: testSliceBools{true, false, false, true, false, false, true, false},
    188 		},
    189 		{
    190 			name:           "invalid-type",
    191 			json:           `["foo",1,2,3,"test"]`,
    192 			expectedResult: testSliceBools{},
    193 			err:            true,
    194 			errType:        InvalidUnmarshalError(""),
    195 		},
    196 		{
    197 			name:           "invalid-json",
    198 			json:           `["hello world]`,
    199 			expectedResult: testSliceBools{},
    200 			err:            true,
    201 			errType:        InvalidJSONError(""),
    202 		},
    203 	}
    204 
    205 	for _, testCase := range testCases {
    206 		t.Run(testCase.name, func(t *testing.T) {
    207 			s := make(testSliceBools, 0)
    208 			dec := BorrowDecoder(strings.NewReader(testCase.json))
    209 			defer dec.Release()
    210 			err := dec.Decode(&s)
    211 			if testCase.err {
    212 				assert.NotNil(t, err, "err should not be nil")
    213 				if testCase.errType != nil {
    214 					assert.IsType(t, testCase.errType, err, "err should be of the given type")
    215 				}
    216 				return
    217 			}
    218 			assert.Nil(t, err, "err should be nil")
    219 			for k, v := range testCase.expectedResult {
    220 				assert.Equal(t, v, s[k], "value at given index should be the same as expected results")
    221 			}
    222 		})
    223 	}
    224 }
    225 
    226 type testSliceSlicesSlices []testSliceInts
    227 
    228 func (t *testSliceSlicesSlices) UnmarshalJSONArray(dec *Decoder) error {
    229 	sl := make(testSliceInts, 0)
    230 	if err := dec.AddArray(&sl); err != nil {
    231 		return err
    232 	}
    233 	*t = append(*t, sl)
    234 	return nil
    235 }
    236 
    237 func TestSliceSlices(t *testing.T) {
    238 	testCases := []struct {
    239 		name           string
    240 		json           string
    241 		expectedResult testSliceSlicesSlices
    242 		err            bool
    243 		errType        interface{}
    244 	}{
    245 		{
    246 			name:           "basic-test",
    247 			json:           `[[1,2],[1,2],[1,2]]`,
    248 			expectedResult: testSliceSlicesSlices{testSliceInts{1, 2}, testSliceInts{1, 2}, testSliceInts{1, 2}},
    249 		},
    250 		{
    251 			name:           "basic-test",
    252 			json:           `[[1,2],null,[1,2]]`,
    253 			expectedResult: testSliceSlicesSlices{testSliceInts{1, 2}, testSliceInts{}, testSliceInts{1, 2}},
    254 		},
    255 		{
    256 			name:           "invalid-type",
    257 			json:           `["foo",1,2,3,"test"]`,
    258 			expectedResult: testSliceSlicesSlices{},
    259 			err:            true,
    260 			errType:        InvalidUnmarshalError(""),
    261 		},
    262 		{
    263 			name:           "invalid-json",
    264 			json:           `["hello world]`,
    265 			expectedResult: testSliceSlicesSlices{},
    266 			err:            true,
    267 			errType:        InvalidJSONError(""),
    268 		},
    269 	}
    270 
    271 	for _, testCase := range testCases {
    272 		t.Run(testCase.name, func(t *testing.T) {
    273 			s := make(testSliceSlicesSlices, 0)
    274 			dec := BorrowDecoder(strings.NewReader(testCase.json))
    275 			defer dec.Release()
    276 			err := dec.Decode(&s)
    277 			if testCase.err {
    278 				assert.NotNil(t, err, "err should not be nil")
    279 				if testCase.errType != nil {
    280 					assert.IsType(t, testCase.errType, err, "err should be of the given type")
    281 				}
    282 				return
    283 			}
    284 			assert.Nil(t, err, "err should be nil")
    285 			for k, v := range testCase.expectedResult {
    286 				assert.Equal(t, v, s[k], "value at given index should be the same as expected results")
    287 			}
    288 		})
    289 	}
    290 }
    291 
    292 type testSliceObjects []*testObject
    293 
    294 func (t *testSliceObjects) UnmarshalJSONArray(dec *Decoder) error {
    295 	obj := &testObject{}
    296 	*t = append(*t, obj)
    297 	return dec.AddObject(obj)
    298 }
    299 
    300 func TestSliceObjects(t *testing.T) {
    301 	testCases := []struct {
    302 		name           string
    303 		json           string
    304 		expectedResult testSliceObjects
    305 		err            bool
    306 		errType        interface{}
    307 	}{
    308 		{
    309 			name: "basic-test",
    310 			json: `[{"testStr":"foo bar","testInt":123},{"testStr":"foo bar","testInt":123}]`,
    311 			expectedResult: testSliceObjects{
    312 				&testObject{
    313 					testStr: "foo bar",
    314 					testInt: 123,
    315 				},
    316 				&testObject{
    317 					testStr: "foo bar",
    318 					testInt: 123,
    319 				},
    320 			},
    321 		},
    322 		{
    323 			name: "basic-test",
    324 			json: `[{"testStr":"foo bar","testInt":123},null,{"testStr":"foo bar","testInt":123}]`,
    325 			expectedResult: testSliceObjects{
    326 				&testObject{
    327 					testStr: "foo bar",
    328 					testInt: 123,
    329 				},
    330 				&testObject{},
    331 				&testObject{
    332 					testStr: "foo bar",
    333 					testInt: 123,
    334 				},
    335 			},
    336 		},
    337 		{
    338 			name:           "invalid-type",
    339 			json:           `["foo",1,2,3,"test"]`,
    340 			expectedResult: testSliceObjects{},
    341 			err:            true,
    342 			errType:        InvalidUnmarshalError(""),
    343 		},
    344 		{
    345 			name:           "invalid-json",
    346 			json:           `["hello world]`,
    347 			expectedResult: testSliceObjects{},
    348 			err:            true,
    349 			errType:        InvalidJSONError(""),
    350 		},
    351 	}
    352 
    353 	for _, testCase := range testCases {
    354 		t.Run(testCase.name, func(t *testing.T) {
    355 			s := make(testSliceObjects, 0)
    356 			dec := BorrowDecoder(strings.NewReader(testCase.json))
    357 			defer dec.Release()
    358 			err := dec.Decode(&s)
    359 			if testCase.err {
    360 				assert.NotNil(t, err, "err should not be nil")
    361 				if testCase.errType != nil {
    362 					assert.IsType(t, testCase.errType, err, "err should be of the given type")
    363 				}
    364 				return
    365 			}
    366 			assert.Nil(t, err, "err should be nil")
    367 			for k, v := range testCase.expectedResult {
    368 				assert.Equal(t, *v, *s[k], "value at given index should be the same as expected results")
    369 			}
    370 		})
    371 	}
    372 }
    373 
    374 type ArrayNull []string
    375 
    376 func (a *ArrayNull) UnmarshalJSONArray(dec *Decoder) error {
    377 	var str string
    378 	if err := dec.String(&str); err != nil {
    379 		return err
    380 	}
    381 	*a = append(*a, str)
    382 	return nil
    383 }
    384 
    385 type ObjectArrayNull struct {
    386 	SubArray *ArrayNull
    387 }
    388 
    389 func (o *ObjectArrayNull) UnmarshalJSONObject(dec *Decoder, k string) error {
    390 	switch k {
    391 	case "subarray":
    392 		return dec.ArrayNull(&o.SubArray)
    393 	}
    394 	return nil
    395 }
    396 
    397 func (o *ObjectArrayNull) NKeys() int {
    398 	return 1
    399 }
    400 
    401 func TestDecodeArrayNullPtr(t *testing.T) {
    402 	t.Run("sub obj should not be nil", func(t *testing.T) {
    403 		var o = &ObjectArrayNull{}
    404 		var err = UnmarshalJSONObject([]byte(`{"subarray": ["test"]}`), o)
    405 		assert.Nil(t, err)
    406 		assert.NotNil(t, o.SubArray)
    407 		assert.Len(t, *o.SubArray, 1)
    408 	})
    409 	t.Run("sub array should be nil", func(t *testing.T) {
    410 		var o = &ObjectArrayNull{}
    411 		var err = UnmarshalJSONObject([]byte(`{"subarray": null}`), o)
    412 		assert.Nil(t, err)
    413 		assert.Nil(t, o.SubArray)
    414 	})
    415 	t.Run("sub array err, not closing arr", func(t *testing.T) {
    416 		var o = &ObjectArrayNull{}
    417 		var err = UnmarshalJSONObject([]byte(`{"subarray": [    `), o)
    418 		assert.NotNil(t, err)
    419 	})
    420 	t.Run("sub array err, invalid string", func(t *testing.T) {
    421 		var o = &ObjectArrayNull{}
    422 		var err = UnmarshalJSONObject([]byte(`{"subarray":[",]}`), o)
    423 		assert.NotNil(t, err)
    424 	})
    425 	t.Run("sub array err, invalid null", func(t *testing.T) {
    426 		var o = &ObjectArrayNull{}
    427 		var err = UnmarshalJSONObject([]byte(`{"subarray":nll}`), o)
    428 		assert.NotNil(t, err)
    429 	})
    430 	t.Run("sub array err, empty", func(t *testing.T) {
    431 		var o = &ObjectArrayNull{}
    432 		var err = UnmarshalJSONObject([]byte(`{"subarray":`), o)
    433 		assert.NotNil(t, err)
    434 	})
    435 }
    436 
    437 type testChannelArray chan *TestObj
    438 
    439 func (c *testChannelArray) UnmarshalJSONArray(dec *Decoder) error {
    440 	obj := &TestObj{}
    441 	if err := dec.AddObject(obj); err != nil {
    442 		return err
    443 	}
    444 	*c <- obj
    445 	return nil
    446 }
    447 
    448 func TestDecoderSliceNull(t *testing.T) {
    449 	json := []byte(`null`)
    450 	v := &testSliceStrings{}
    451 	err := Unmarshal(json, v)
    452 	assert.Nil(t, err, "Err must be nil")
    453 	assert.Equal(t, len(*v), 0, "v must be of len 0")
    454 }
    455 
    456 func TestDecodeSliceInvalidType(t *testing.T) {
    457 	result := testSliceObjects{}
    458 	err := UnmarshalJSONArray([]byte(`{}`), &result)
    459 	assert.NotNil(t, err, "err should not be nil")
    460 	assert.IsType(t, InvalidUnmarshalError(""), err, "err should be of type InvalidUnmarshalError")
    461 	assert.Equal(t, "Cannot unmarshal JSON to type '*gojay.testSliceObjects'", err.Error(), "err should not be nil")
    462 }
    463 
    464 func TestDecoderChannelOfObjectsBasic(t *testing.T) {
    465 	json := []byte(`[
    466 		{
    467 			"test": 245,
    468 			"test2": -246,
    469 			"test3": "string"
    470 		},
    471 		{
    472 			"test": 247,
    473 			"test2": 248,
    474 			"test3": "string"
    475 		},
    476 		{
    477 			"test": 777,
    478 			"test2": 456,
    479 			"test3": "string"
    480 		}
    481 	]`)
    482 	testChan := testChannelArray(make(chan *TestObj, 3))
    483 	err := UnmarshalJSONArray(json, &testChan)
    484 	assert.Nil(t, err, "Err must be nil")
    485 	ct := 0
    486 	l := len(testChan)
    487 	for range testChan {
    488 		ct++
    489 		if ct == l {
    490 			break
    491 		}
    492 	}
    493 	assert.Equal(t, ct, 3)
    494 }
    495 
    496 func TestDecoderSliceInvalidJSON(t *testing.T) {
    497 	json := []byte(`hello`)
    498 	testArr := testSliceInts{}
    499 	err := UnmarshalJSONArray(json, &testArr)
    500 	assert.NotNil(t, err, "Err must not be nil as JSON is invalid")
    501 	assert.IsType(t, InvalidJSONError(""), err, "err message must be 'Invalid JSON'")
    502 }
    503 
    504 func TestDecoderSliceDecoderAPI(t *testing.T) {
    505 	json := `["string","string1"]`
    506 	testArr := testSliceStrings{}
    507 	dec := NewDecoder(strings.NewReader(json))
    508 	err := dec.DecodeArray(&testArr)
    509 	assert.Nil(t, err, "Err must be nil")
    510 	assert.Len(t, testArr, 2, "testArr should be of len 2")
    511 	assert.Equal(t, "string", testArr[0], "testArr[0] should be 'string'")
    512 	assert.Equal(t, "string1", testArr[1], "testArr[1] should be 'string1'")
    513 }
    514 
    515 func TestDecoderSliceDecoderAPIError(t *testing.T) {
    516 	testArr := testSliceInts{}
    517 	dec := NewDecoder(strings.NewReader(`hello`))
    518 	err := dec.DecodeArray(&testArr)
    519 	assert.NotNil(t, err, "Err must not be nil as JSON is invalid")
    520 	assert.IsType(t, InvalidJSONError(""), err, "err message must be 'Invalid JSON'")
    521 }
    522 
    523 func TestUnmarshalJSONArrays(t *testing.T) {
    524 	testCases := []struct {
    525 		name         string
    526 		v            UnmarshalerJSONArray
    527 		d            []byte
    528 		expectations func(err error, v interface{}, t *testing.T)
    529 	}{
    530 		{
    531 			v:    new(testDecodeSlice),
    532 			d:    []byte(`[{"test":"test"}]`),
    533 			name: "test decode slice",
    534 			expectations: func(err error, v interface{}, t *testing.T) {
    535 				vtPtr := v.(*testDecodeSlice)
    536 				vt := *vtPtr
    537 				assert.Nil(t, err, "err must be nil")
    538 				assert.Len(t, vt, 1, "len of vt must be 1")
    539 				assert.Equal(t, "test", vt[0].test, "vt[0].test must be equal to 'test'")
    540 			},
    541 		},
    542 		{
    543 			v:    new(testDecodeSlice),
    544 			d:    []byte(`[{"test":"test"},{"test":"test2"}]`),
    545 			name: "test decode slice",
    546 			expectations: func(err error, v interface{}, t *testing.T) {
    547 				vtPtr := v.(*testDecodeSlice)
    548 				vt := *vtPtr
    549 				assert.Nil(t, err, "err must be nil")
    550 				assert.Len(t, vt, 2, "len of vt must be 2")
    551 				assert.Equal(t, "test", vt[0].test, "vt[0].test must be equal to 'test'")
    552 				assert.Equal(t, "test2", vt[1].test, "vt[1].test must be equal to 'test2'")
    553 			},
    554 		},
    555 		{
    556 			v:    new(testDecodeSlice),
    557 			d:    []byte(`invalid json`),
    558 			name: "test decode object null",
    559 			expectations: func(err error, v interface{}, t *testing.T) {
    560 				assert.NotNil(t, err, "err must not be nil")
    561 				assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError")
    562 			},
    563 		},
    564 	}
    565 	for _, testCase := range testCases {
    566 		testCase := testCase
    567 		t.Run(testCase.name, func(*testing.T) {
    568 			err := UnmarshalJSONArray(testCase.d, testCase.v)
    569 			testCase.expectations(err, testCase.v, t)
    570 		})
    571 	}
    572 }
    573 
    574 func TestSkipArray(t *testing.T) {
    575 	testCases := []struct {
    576 		name         string
    577 		json         string
    578 		expectations func(*testing.T, int, error)
    579 	}{
    580 		{
    581 			name: "basic",
    582 			json: `"testbasic"]`,
    583 			expectations: func(t *testing.T, i int, err error) {
    584 				assert.Equal(t, len(`"testbasic"]`), i)
    585 				assert.Nil(t, err)
    586 			},
    587 		},
    588 		{
    589 			name: "complex escape string",
    590 			json: `"test \\\\\" escape"]`,
    591 			expectations: func(t *testing.T, i int, err error) {
    592 				assert.Equal(t, len(`"test \\\\\" escape"]`), i)
    593 				assert.Nil(t, err)
    594 			},
    595 		},
    596 		{
    597 			name: "complex escape slash",
    598 			json: `"test \\\\\\"]`,
    599 			expectations: func(t *testing.T, i int, err error) {
    600 				assert.Equal(t, len(`"test \\\\\\"]`), i)
    601 				assert.Nil(t, err)
    602 			},
    603 		},
    604 		{
    605 			json: `"test \n"]`,
    606 			expectations: func(t *testing.T, i int, err error) {
    607 				assert.Equal(t, len(`"test \n"]`), i)
    608 				assert.Nil(t, err)
    609 			},
    610 		},
    611 	}
    612 
    613 	for _, test := range testCases {
    614 		t.Run(test.name, func(t *testing.T) {
    615 			dec := NewDecoder(strings.NewReader(test.json))
    616 			i, err := dec.skipArray()
    617 			test.expectations(t, i, err)
    618 		})
    619 	}
    620 }
    621 
    622 func TestDecodeArrayEmpty(t *testing.T) {
    623 	v := new(testDecodeSlice)
    624 	dec := NewDecoder(strings.NewReader(""))
    625 	err := dec.Decode(v)
    626 	assert.NotNil(t, err, "err should not be nil")
    627 	assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
    628 }
    629 
    630 func TestDecodeArraySkipError(t *testing.T) {
    631 	v := new(testDecodeSlice)
    632 	dec := NewDecoder(strings.NewReader("34fef"))
    633 	err := dec.Decode(v)
    634 	assert.NotNil(t, err, "err should not be nil")
    635 	assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
    636 }
    637 
    638 func TestDecodeArrayNullError(t *testing.T) {
    639 	v := new(testDecodeSlice)
    640 	dec := NewDecoder(strings.NewReader("nall"))
    641 	err := dec.Decode(v)
    642 	assert.NotNil(t, err, "err should not be nil")
    643 	assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
    644 }
    645 
    646 func TestDecoderArrayFunc(t *testing.T) {
    647 	var f DecodeArrayFunc
    648 	assert.True(t, f.IsNil())
    649 }
    650 
    651 type testArrayStrings [3]string
    652 
    653 func (a *testArrayStrings) UnmarshalJSONArray(dec *Decoder) error {
    654 	var str string
    655 	if err := dec.String(&str); err != nil {
    656 		return err
    657 	}
    658 	a[dec.Index()] = str
    659 	return nil
    660 }
    661 
    662 func TestArrayStrings(t *testing.T) {
    663 	data := []byte(`["a", "b", "c"]`)
    664 	arr := testArrayStrings{}
    665 	err := Unmarshal(data, &arr)
    666 	assert.Nil(t, err, "err must be nil")
    667 	assert.Equal(t, "a", arr[0], "arr[0] must be equal to 'a'")
    668 	assert.Equal(t, "b", arr[1], "arr[1] must be equal to 'b'")
    669 	assert.Equal(t, "c", arr[2], "arr[2] must be equal to 'c'")
    670 }
    671 
    672 type testSliceArraysStrings struct {
    673 	arrays []testArrayStrings
    674 	t      *testing.T
    675 }
    676 
    677 func (s *testSliceArraysStrings) UnmarshalJSONArray(dec *Decoder) error {
    678 	var a testArrayStrings
    679 	assert.Equal(s.t, len(s.arrays), dec.Index(), "decoded array index must be equal to current slice len")
    680 	if err := dec.AddArray(&a); err != nil {
    681 		return err
    682 	}
    683 	assert.Equal(s.t, len(s.arrays), dec.Index(), "decoded array index must be equal to current slice len")
    684 	s.arrays = append(s.arrays, a)
    685 	return nil
    686 }
    687 
    688 func TestIndex(t *testing.T) {
    689 	testCases := []struct {
    690 		name           string
    691 		json           string
    692 		expectedResult []testArrayStrings
    693 	}{
    694 		{
    695 			name:           "basic-test",
    696 			json:           `[["a","b","c"],["1","2","3"],["x","y","z"]]`,
    697 			expectedResult: []testArrayStrings{{"a", "b", "c"}, {"1", "2", "3"}, {"x", "y", "z"}},
    698 		},
    699 		{
    700 			name:           "basic-test-null",
    701 			json:           `[["a","b","c"],null,["x","y","z"]]`,
    702 			expectedResult: []testArrayStrings{{"a", "b", "c"}, {"", "", ""}, {"x", "y", "z"}},
    703 		},
    704 	}
    705 
    706 	for _, testCase := range testCases {
    707 		t.Run(testCase.name, func(t *testing.T) {
    708 			s := make([]testArrayStrings, 0)
    709 			dec := BorrowDecoder(strings.NewReader(testCase.json))
    710 			defer dec.Release()
    711 			a := testSliceArraysStrings{arrays: s, t: t}
    712 			err := dec.Decode(&a)
    713 			assert.Nil(t, err, "err should be nil")
    714 			assert.Zero(t, dec.Index(), "Index() must return zero after decoding")
    715 			for k, v := range testCase.expectedResult {
    716 				assert.Equal(t, v, a.arrays[k], "value at given index should be the same as expected results")
    717 			}
    718 		})
    719 	}
    720 }