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 }