gojay

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

decode_object_test.go (48082B)


      1 package gojay
      2 
      3 import (
      4 	"fmt"
      5 	"io"
      6 	"reflect"
      7 	"strings"
      8 	"testing"
      9 
     10 	"github.com/stretchr/testify/assert"
     11 )
     12 
     13 func makePointer(v interface{}) interface{} {
     14 	var ptr = reflect.New(reflect.TypeOf(v))
     15 	ptr.Elem().Set(reflect.ValueOf(v))
     16 	return ptr.Interface()
     17 }
     18 
     19 func TestDecodeObjectBasic(t *testing.T) {
     20 	testCases := []struct {
     21 		name            string
     22 		json            string
     23 		expectedResult  testObject
     24 		err             bool
     25 		errType         interface{}
     26 		skipCheckResult bool
     27 	}{
     28 		{
     29 			name: "basic",
     30 			json: `{
     31 						"testStr": "hello world!",
     32 						"testStrNull":  "hello world!",
     33 						"testInt": 4535,
     34 						"testIntNull": 4535,
     35 						"testBool": true,
     36 						"testBoolNull": true,
     37 						"testFloat32": 2.345,
     38 						"testFloat32Null": 2.345,
     39 						"testFloat64": 123.677,
     40 						"testFloat64Null": 123.677,
     41 						"testInt8": 23,
     42 						"testInt8Null": 23,
     43 						"testInt16": 1245,
     44 						"testInt16Null": 1245,
     45 						"testInt32": 456778,
     46 						"testInt32Null": 456778,
     47 						"testInt64": 1446685358,
     48 						"testInt64Null": 1446685358,
     49 						"testUint8": 255,
     50 						"testUint8Null": 255,
     51 						"testUint16": 3455,
     52 						"testUint16Null": 3455,
     53 						"testUint32": 343443,
     54 						"testUint32Null": 343443,
     55 						"testUint64": 545665757,
     56 						"testUint64Null": 545665757,
     57 						"testSubObjectNull": {
     58 							"testStr": "1"
     59 						}
     60 					}`,
     61 			expectedResult: testObject{
     62 				testStr:         "hello world!",
     63 				testStrNull:     makePointer("hello world!").(*string),
     64 				testInt:         4535,
     65 				testIntNull:     makePointer(4535).(*int),
     66 				testBool:        true,
     67 				testBoolNull:    makePointer(true).(*bool),
     68 				testFloat32:     2.345,
     69 				testFloat32Null: makePointer(float32(2.345)).(*float32),
     70 				testFloat64:     123.677,
     71 				testFloat64Null: makePointer(float64(123.677)).(*float64),
     72 				testInt8:        23,
     73 				testInt8Null:    makePointer(int8(23)).(*int8),
     74 				testInt16:       1245,
     75 				testInt16Null:   makePointer(int16(1245)).(*int16),
     76 				testInt32:       456778,
     77 				testInt32Null:   makePointer(int32(456778)).(*int32),
     78 				testInt64:       1446685358,
     79 				testInt64Null:   makePointer(int64(1446685358)).(*int64),
     80 				testUint8:       255,
     81 				testUint8Null:   makePointer(uint8(255)).(*uint8),
     82 				testUint16:      3455,
     83 				testUint16Null:  makePointer(uint16(3455)).(*uint16),
     84 				testUint32:      343443,
     85 				testUint32Null:  makePointer(uint32(343443)).(*uint32),
     86 				testUint64:      545665757,
     87 				testUint64Null:  makePointer(uint64(545665757)).(*uint64),
     88 			},
     89 			err: false,
     90 		},
     91 		{
     92 			name: "basic-with-exponent",
     93 			json: `{
     94 						"testStr": "hello world!",
     95 						"testInt": 3e3,
     96 						"testBool": true,
     97 						"testFloat32": 2.345,
     98 						"testFloat64": 123.677,
     99 						"testInt8": 23,
    100 						"testInt16": 1245,
    101 						"testInt32": 456778,
    102 						"testInt64": 1446685358,
    103 						"testUint8": 255,
    104 						"testUint16": 3455,
    105 						"testUint32": 343443,
    106 						"testUint64": 545665757
    107 					}`,
    108 			expectedResult: testObject{
    109 				testStr:     "hello world!",
    110 				testInt:     3000,
    111 				testBool:    true,
    112 				testFloat32: 2.345,
    113 				testFloat64: 123.677,
    114 				testInt8:    23,
    115 				testInt16:   1245,
    116 				testInt32:   456778,
    117 				testInt64:   1446685358,
    118 				testUint8:   255,
    119 				testUint16:  3455,
    120 				testUint32:  343443,
    121 				testUint64:  545665757,
    122 			},
    123 			err: false,
    124 		},
    125 		{
    126 			name: "basic-with-exponent3",
    127 			json: `{
    128 						"testStr": "hello world!",
    129 						"testInt": 3e-3,
    130 						"testBool": true,
    131 						"testFloat32": 2.345,
    132 						"testFloat64": 12e-3,
    133 						"testInt8": 23,
    134 						"testInt16": 1245,
    135 						"testInt32": 456778,
    136 						"testInt64": 1446685358,
    137 						"testUint8": 255,
    138 						"testUint16": 3455,
    139 						"testUint32": 343443,
    140 						"testUint64": 545665757
    141 					}`,
    142 			expectedResult: testObject{
    143 				testStr:     "hello world!",
    144 				testInt:     0,
    145 				testBool:    true,
    146 				testFloat32: 2.345,
    147 				testFloat64: 0.012,
    148 				testInt8:    23,
    149 				testInt16:   1245,
    150 				testInt32:   456778,
    151 				testInt64:   1446685358,
    152 				testUint8:   255,
    153 				testUint16:  3455,
    154 				testUint32:  343443,
    155 				testUint64:  545665757,
    156 			},
    157 			err: false,
    158 		},
    159 		{
    160 			name:           "basic-err-invalid-type",
    161 			json:           `1`,
    162 			expectedResult: testObject{},
    163 			err:            true,
    164 			errType:        InvalidUnmarshalError(""),
    165 		},
    166 		{
    167 			name:           "basic-err-invalid-json",
    168 			json:           `hello`,
    169 			expectedResult: testObject{},
    170 			err:            true,
    171 			errType:        InvalidJSONError(""),
    172 		},
    173 		{
    174 			name:           "basic-err-invalid-json",
    175 			json:           `nall`,
    176 			expectedResult: testObject{},
    177 			err:            true,
    178 			errType:        InvalidJSONError(""),
    179 		},
    180 		{
    181 			name:           "basic-err-invalid-type",
    182 			json:           ``,
    183 			expectedResult: testObject{},
    184 			err:            true,
    185 			errType:        InvalidJSONError(""),
    186 		},
    187 		{
    188 			name: "basic-err",
    189 			json: `{
    190 						"testStr": "hello world!",
    191 						"testInt": 453q5,
    192 						"testBool": trae,
    193 						"testFloat32": 2q.345,
    194 						"testFloat64": 12x3.677,
    195 						"testInt8": 2s3,
    196 						"testInt16": 1245,
    197 						"testInt32": 4567q78,
    198 						"testInt64": 14466e85358,
    199 						"testUint8": 2s55,
    200 						"testUint16": 345i5,
    201 						"testUint32": 343q443,
    202 						"testUint64": 5456657z57
    203 					}`,
    204 			expectedResult: testObject{},
    205 			err:            true,
    206 		},
    207 		{
    208 			name: "basic-err2",
    209 			json: `{
    210 						"testStr": "hello world!",
    211 						"testInt": 4535,
    212 						"testBool": true,
    213 						"testFloat32": 2.345,
    214 						"testFloat64": 123.677,
    215 						"testInt8": 23,
    216 						"testInt16": 1245,
    217 						"testInt32": 4567x78,
    218 						"testInt64": 1446685358,
    219 						"testUint8": 255,
    220 						"testUint16": 3455,
    221 						"testUint32": 343443,
    222 						"testUint64": 545665757
    223 					}`,
    224 			expectedResult: testObject{},
    225 			err:            true,
    226 		},
    227 		{
    228 			name: "basic-err-float32",
    229 			json: `{
    230 						"testStr": "hello world!",
    231 						"testInt": 4535,
    232 						"testBool": true,
    233 						"testFloat32": 2q.345,
    234 						"testFloat64": 123.677,
    235 						"testInt8": 23,
    236 						"testInt16": 1245,
    237 						"testInt32": 456778,
    238 						"testInt64": 1446685358,
    239 						"testUint8": 255,
    240 						"testUint16": 3455,
    241 						"testUint32": 343443,
    242 						"testUint64": 545665757
    243 					}`,
    244 			expectedResult: testObject{},
    245 			err:            true,
    246 		},
    247 		{
    248 			name: "basic-err-float64",
    249 			json: `{
    250 						"testStr": "hello world!",
    251 						"testInt": 4535,
    252 						"testBool": true,
    253 						"testFloat32": 2.345,
    254 						"testFloat64": 1x23.677,
    255 						"testInt8": 23,
    256 						"testInt16": 1245,
    257 						"testInt32": 456778,
    258 						"testInt64": 1446685358,
    259 						"testUint8": 255,
    260 						"testUint16": 3455,
    261 						"testUint32": 343443,
    262 						"testUint64": 545665757
    263 					}`,
    264 			expectedResult: testObject{},
    265 			err:            true,
    266 		},
    267 		{
    268 			name: "basic-err3",
    269 			json: `{
    270 						"testStr": "hello world!",
    271 						"testInt": 4535,
    272 						"testBool": true,
    273 						"testFloat32": 2.345,
    274 						"testFloat64": 123.677,
    275 						"testInt8": 2q3,
    276 						"testInt16": 1245,
    277 						"testInt32": 456778,
    278 						"testInt64": 1446685358,
    279 						"testUint8": 255,
    280 						"testUint16": 3455,
    281 						"testUint32": 343443,
    282 						"testUint64": 545665757
    283 					}`,
    284 			expectedResult: testObject{},
    285 			err:            true,
    286 		},
    287 		{
    288 			name: "basic-err-int16",
    289 			json: `{
    290 						"testStr": "hello world!",
    291 						"testInt": 4535,
    292 						"testBool": true,
    293 						"testFloat32": 2.345,
    294 						"testFloat64": 123.677,
    295 						"testInt8": 23,
    296 						"testInt16": 1x245,
    297 						"testInt32": 456778,
    298 						"testInt64": 1446685358,
    299 						"testUint8": 255,
    300 						"testUint16": 3455,
    301 						"testUint32": 343443,
    302 						"testUint64": 545665757
    303 					}`,
    304 			expectedResult: testObject{},
    305 			err:            true,
    306 		},
    307 		{
    308 			name: "basic-err-int64",
    309 			json: `{
    310 						"testStr": "hello world!",
    311 						"testInt": 4535,
    312 						"testBool": true,
    313 						"testFloat32": 2.345,
    314 						"testFloat64": 123.677,
    315 						"testInt8": 23,
    316 						"testInt16": 1245,
    317 						"testInt32": 456778,
    318 						"testInt64": 1446q685358,
    319 						"testUint8": 255,
    320 						"testUint16": 3455,
    321 						"testUint32": 343443,
    322 						"testUint64": 545665757
    323 					}`,
    324 			expectedResult: testObject{},
    325 			err:            true,
    326 		},
    327 		{
    328 			name: "basic-err-uint8",
    329 			json: `{
    330 						"testStr": "hello world!",
    331 						"testInt": 4535,
    332 						"testBool": true,
    333 						"testFloat32": 2.345,
    334 						"testFloat64": 123.677,
    335 						"testInt8": 23,
    336 						"testInt16": 1245,
    337 						"testInt32": 456778,
    338 						"testInt64": 1446685358,
    339 						"testUint8": 2x55,
    340 						"testUint16": 3455,
    341 						"testUint32": 343443,
    342 						"testUint64": 545665757
    343 					}`,
    344 			expectedResult: testObject{},
    345 			err:            true,
    346 		},
    347 		{
    348 			name: "basic-err-uint16",
    349 			json: `{
    350 						"testStr": "hello world!",
    351 						"testInt": 4535,
    352 						"testBool": true,
    353 						"testFloat32": 2.345,
    354 						"testFloat64": 123.677,
    355 						"testInt8": 23,
    356 						"testInt16": 1245,
    357 						"testInt32": 456778,
    358 						"testInt64": 1446685358,
    359 						"testUint8": 255,
    360 						"testUint16": 3x455,
    361 						"testUint32": 343443,
    362 						"testUint64": 545665757
    363 					}`,
    364 			expectedResult: testObject{},
    365 			err:            true,
    366 		},
    367 		{
    368 			name: "basic-err-uint32",
    369 			json: `{
    370 						"testStr": "hello world!",
    371 						"testInt": 4535,
    372 						"testBool": true,
    373 						"testFloat32": 2.345,
    374 						"testFloat64": 123.677,
    375 						"testInt8": 23,
    376 						"testInt16": 1245,
    377 						"testInt32": 456778,
    378 						"testInt64": 1446685358,
    379 						"testUint8": 255,
    380 						"testUint16": 3455,
    381 						"testUint32": 3x43443,
    382 						"testUint64": 545665757
    383 					}`,
    384 			expectedResult: testObject{},
    385 			err:            true,
    386 		},
    387 		{
    388 			name: "basic-err-uint64",
    389 			json: `{
    390 						"testStr": "hello world!",
    391 						"testInt": 4535,
    392 						"testBool": true,
    393 						"testFloat32": 2.345,
    394 						"testFloat64": 123.677,
    395 						"testInt8": 23,
    396 						"testInt16": 1245,
    397 						"testInt32": 456778,
    398 						"testInt64": 1446685358,
    399 						"testUint8": 255,
    400 						"testUint16": 3455,
    401 						"testUint32": 343443,
    402 						"testUint64": 5456x65757
    403 					}`,
    404 			expectedResult: testObject{},
    405 			err:            true,
    406 		},
    407 		{
    408 			name: "basic-skip-data",
    409 			json: `{
    410 				"testStr": "hello world!",
    411 				"testInt": 4535,
    412 				"testBool": true,
    413 				"testFloat32": 2.345,
    414 				"testFloat64": 123.677,
    415 				"testInt8": 23,
    416 				"skipObject": {
    417 					"escapedString": "string with escaped \\n new line"
    418 				},
    419 				"testInt16": 1245,
    420 				"testInt32": 456778,
    421 				"testInt64": 1446685358,
    422 				"testUint8": 255,
    423 				"skipArray": [[],[],{}],
    424 				"testUint16": 3455,
    425 				"skipBool": true,
    426 				"skipNull": null,
    427 				"testUint32": 343443,
    428 				"testUint64": 545665757,
    429 				"skipString": "skipping string with escaped \\n new line",
    430 				"skipInt": 3,
    431 			}`,
    432 			expectedResult: testObject{
    433 				testStr:     "hello world!",
    434 				testInt:     4535,
    435 				testBool:    true,
    436 				testFloat32: 2.345,
    437 				testFloat64: 123.677,
    438 				testInt8:    23,
    439 				testInt16:   1245,
    440 				testInt32:   456778,
    441 				testInt64:   1446685358,
    442 				testUint8:   255,
    443 				testUint16:  3455,
    444 				testUint32:  343443,
    445 				testUint64:  545665757,
    446 			},
    447 			err: false,
    448 		},
    449 		{
    450 			name: "basic-skip-data-error-uint8-negative",
    451 			json: `{
    452 				"testStr": "hello world!",
    453 				"testInt": 4535,
    454 				"testBool": true,
    455 				"testFloat32": 2.345,
    456 				"testFloat64": 123.677,
    457 				"testInt8": 23,
    458 				"skipObject": {
    459 					"escapedString": "string with escaped \\n new line"
    460 				},
    461 				"testInt16": 1245,
    462 				"testInt32": 456778,
    463 				"testInt64": 1446685358,
    464 				"testUint8": -255,
    465 				"skipArray": [[],[],{}],
    466 				"testUint16": 3455,
    467 				"skipBool": true,
    468 				"skipNull": null,
    469 				"testUint32": 343443,
    470 				"testUint64": 545665757,
    471 				"skipString": "skipping string with escaped \\n new line",
    472 				"skipInt": 3
    473 			}`,
    474 			expectedResult: testObject{
    475 				testStr:     "hello world!",
    476 				testInt:     4535,
    477 				testBool:    true,
    478 				testFloat32: 2.345,
    479 				testFloat64: 123.677,
    480 				testInt8:    23,
    481 				testInt16:   1245,
    482 				testInt32:   456778,
    483 				testInt64:   1446685358,
    484 				testUint8:   0,
    485 				testUint16:  3455,
    486 				testUint32:  343443,
    487 				testUint64:  545665757,
    488 			},
    489 			err: true,
    490 		},
    491 		{
    492 			name: "skip-data-with-unicode",
    493 			json: `{
    494 				"skipString": "hello\u1234\u2123",
    495 				"testStr": "hello world!",
    496 				"testInt": 4535,
    497 				"testBool": true,
    498 				"testFloat32": 2.345,
    499 				"testFloat64": 123.677,
    500 				"testInt8": 23,
    501 				"skipObject": {
    502 					"escapedString": "string with unicode \u1234\u1234\u1234"
    503 				},
    504 				"testInt16": 1245,
    505 				"testInt32": 456778,
    506 				"testInt64": 1446685358,
    507 				"testUint8": 255,
    508 				"skipArray": [[],[],{}],
    509 				"testUint16": 3455,
    510 				"skipBool": true,
    511 				"skipNull": null,
    512 				"testUint32": 343443,
    513 				"testUint64": 545665757,
    514 				"skipInt": 3
    515 			}`,
    516 			expectedResult: testObject{
    517 				testStr:     "hello world!",
    518 				testInt:     4535,
    519 				testBool:    true,
    520 				testFloat32: 2.345,
    521 				testFloat64: 123.677,
    522 				testInt8:    23,
    523 				testInt16:   1245,
    524 				testInt32:   456778,
    525 				testInt64:   1446685358,
    526 				testUint8:   255,
    527 				testUint16:  3455,
    528 				testUint32:  343443,
    529 				testUint64:  545665757,
    530 			},
    531 			err: false,
    532 		},
    533 	}
    534 
    535 	for _, testCase := range testCases {
    536 		t.Run(testCase.name, func(t *testing.T) {
    537 			s := testObject{}
    538 			dec := BorrowDecoder(strings.NewReader(testCase.json))
    539 			defer dec.Release()
    540 			err := dec.Decode(&s)
    541 			if testCase.err {
    542 				t.Log(err)
    543 				assert.NotNil(t, err, "err should not be nil")
    544 				if testCase.errType != nil {
    545 					assert.IsType(t, testCase.errType, err, "err should be of the given type")
    546 				}
    547 				return
    548 			}
    549 			assert.Nil(t, err, "err should be nil")
    550 			if !testCase.skipCheckResult {
    551 				assert.Equal(t, testCase.expectedResult, s, "value at given index should be the same as expected results")
    552 			}
    553 		})
    554 	}
    555 }
    556 
    557 func TestDecodeObjectBasic0Keys(t *testing.T) {
    558 	testCases := []struct {
    559 		name            string
    560 		json            string
    561 		expectedResult  testObject0Keys
    562 		err             bool
    563 		errType         interface{}
    564 		skipCheckResult bool
    565 	}{
    566 		{
    567 			name: "basic",
    568 			json: `{
    569 						"testStr": "hello world!",
    570 						"testInt": 4535,
    571 						"testBool": true,
    572 						"testFloat32": 2.345,
    573 						"testFloat64": 123.677,
    574 						"testInt8": 23,
    575 						"testInt16": 1245,
    576 						"testInt32": 456778,
    577 						"testInt64": 1446685358,
    578 						"testUint8": 255,
    579 						"testUint16": 3455,
    580 						"testUint32": 343443,
    581 						"testUint64": 545665757
    582 					}`,
    583 			expectedResult: testObject0Keys{
    584 				testStr:     "hello world!",
    585 				testInt:     4535,
    586 				testBool:    true,
    587 				testFloat32: 2.345,
    588 				testFloat64: 123.677,
    589 				testInt8:    23,
    590 				testInt16:   1245,
    591 				testInt32:   456778,
    592 				testInt64:   1446685358,
    593 				testUint8:   255,
    594 				testUint16:  3455,
    595 				testUint32:  343443,
    596 				testUint64:  545665757,
    597 			},
    598 			err: false,
    599 		},
    600 		{
    601 			name:           "basic-err-invalid-type",
    602 			json:           `1`,
    603 			expectedResult: testObject0Keys{},
    604 			err:            true,
    605 			errType:        InvalidUnmarshalError(""),
    606 		},
    607 		{
    608 			name:           "basic-err-invalid-json",
    609 			json:           `hello`,
    610 			expectedResult: testObject0Keys{},
    611 			err:            true,
    612 			errType:        InvalidJSONError(""),
    613 		},
    614 		{
    615 			name:           "basic-err-invalid-json",
    616 			json:           `nall`,
    617 			expectedResult: testObject0Keys{},
    618 			err:            true,
    619 			errType:        InvalidJSONError(""),
    620 		},
    621 		{
    622 			name:           "basic-err-invalid-type",
    623 			json:           ``,
    624 			expectedResult: testObject0Keys{},
    625 			err:            true,
    626 			errType:        InvalidJSONError(""),
    627 		},
    628 		{
    629 			name: "basic-err",
    630 			json: `{
    631 						"testStr": "hello world!",
    632 						"testInt": 453q5,
    633 						"testBool": trae,
    634 						"testFloat32": 2q.345,
    635 						"testFloat64": 12x3.677,
    636 						"testInt8": 2s3,
    637 						"testInt16": 1245,
    638 						"testInt32": 4567q78,
    639 						"testInt64": 14466e85358,
    640 						"testUint8": 2s55,
    641 						"testUint16": 345i5,
    642 						"testUint32": 343q443,
    643 						"testUint64": 5456657z57
    644 					}`,
    645 			expectedResult: testObject0Keys{},
    646 			err:            true,
    647 		},
    648 		{
    649 			name: "basic-err2",
    650 			json: `{
    651 						"testStr": "hello world!",
    652 						"testInt": 4535,
    653 						"testBool": true,
    654 						"testFloat32": 2.345,
    655 						"testFloat64": 123.677,
    656 						"testInt8": 23,
    657 						"testInt16": 1245,
    658 						"testInt32": 4567x78,
    659 						"testInt64": 1446685358,
    660 						"testUint8": 255,
    661 						"testUint16": 3455,
    662 						"testUint32": 343443,
    663 						"testUint64": 545665757
    664 					}`,
    665 			expectedResult: testObject0Keys{},
    666 			err:            true,
    667 		},
    668 		{
    669 			name: "basic-err-float32",
    670 			json: `{
    671 						"testStr": "hello world!",
    672 						"testInt": 4535,
    673 						"testBool": true,
    674 						"testFloat32": 2q.345,
    675 						"testFloat64": 123.677,
    676 						"testInt8": 23,
    677 						"testInt16": 1245,
    678 						"testInt32": 456778,
    679 						"testInt64": 1446685358,
    680 						"testUint8": 255,
    681 						"testUint16": 3455,
    682 						"testUint32": 343443,
    683 						"testUint64": 545665757
    684 					}`,
    685 			expectedResult: testObject0Keys{},
    686 			err:            true,
    687 		},
    688 		{
    689 			name: "basic-err-float64",
    690 			json: `{
    691 						"testStr": "hello world!",
    692 						"testInt": 4535,
    693 						"testBool": true,
    694 						"testFloat32": 2.345,
    695 						"testFloat64": 1x23.677,
    696 						"testInt8": 23,
    697 						"testInt16": 1245,
    698 						"testInt32": 456778,
    699 						"testInt64": 1446685358,
    700 						"testUint8": 255,
    701 						"testUint16": 3455,
    702 						"testUint32": 343443,
    703 						"testUint64": 545665757
    704 					}`,
    705 			expectedResult: testObject0Keys{},
    706 			err:            true,
    707 		},
    708 		{
    709 			name: "basic-err3",
    710 			json: `{
    711 						"testStr": "hello world!",
    712 						"testInt": 4535,
    713 						"testBool": true,
    714 						"testFloat32": 2.345,
    715 						"testFloat64": 123.677,
    716 						"testInt8": 2q3,
    717 						"testInt16": 1245,
    718 						"testInt32": 456778,
    719 						"testInt64": 1446685358,
    720 						"testUint8": 255,
    721 						"testUint16": 3455,
    722 						"testUint32": 343443,
    723 						"testUint64": 545665757
    724 					}`,
    725 			expectedResult: testObject0Keys{},
    726 			err:            true,
    727 		},
    728 		{
    729 			name: "basic-err-int16",
    730 			json: `{
    731 						"testStr": "hello world!",
    732 						"testInt": 4535,
    733 						"testBool": true,
    734 						"testFloat32": 2.345,
    735 						"testFloat64": 123.677,
    736 						"testInt8": 23,
    737 						"testInt16": 1x245,
    738 						"testInt32": 456778,
    739 						"testInt64": 1446685358,
    740 						"testUint8": 255,
    741 						"testUint16": 3455,
    742 						"testUint32": 343443,
    743 						"testUint64": 545665757
    744 					}`,
    745 			expectedResult: testObject0Keys{},
    746 			err:            true,
    747 		},
    748 		{
    749 			name: "basic-err-int64",
    750 			json: `{
    751 						"testStr": "hello world!",
    752 						"testInt": 4535,
    753 						"testBool": true,
    754 						"testFloat32": 2.345,
    755 						"testFloat64": 123.677,
    756 						"testInt8": 23,
    757 						"testInt16": 1245,
    758 						"testInt32": 456778,
    759 						"testInt64": 1446q685358,
    760 						"testUint8": 255,
    761 						"testUint16": 3455,
    762 						"testUint32": 343443,
    763 						"testUint64": 545665757
    764 					}`,
    765 			expectedResult: testObject0Keys{},
    766 			err:            true,
    767 		},
    768 		{
    769 			name: "basic-err-uint8",
    770 			json: `{
    771 						"testStr": "hello world!",
    772 						"testInt": 4535,
    773 						"testBool": true,
    774 						"testFloat32": 2.345,
    775 						"testFloat64": 123.677,
    776 						"testInt8": 23,
    777 						"testInt16": 1245,
    778 						"testInt32": 456778,
    779 						"testInt64": 1446685358,
    780 						"testUint8": 2x55,
    781 						"testUint16": 3455,
    782 						"testUint32": 343443,
    783 						"testUint64": 545665757
    784 					}`,
    785 			expectedResult: testObject0Keys{},
    786 			err:            true,
    787 		},
    788 		{
    789 			name: "basic-err-uint16",
    790 			json: `{
    791 						"testStr": "hello world!",
    792 						"testInt": 4535,
    793 						"testBool": true,
    794 						"testFloat32": 2.345,
    795 						"testFloat64": 123.677,
    796 						"testInt8": 23,
    797 						"testInt16": 1245,
    798 						"testInt32": 456778,
    799 						"testInt64": 1446685358,
    800 						"testUint8": 255,
    801 						"testUint16": 3x455,
    802 						"testUint32": 343443,
    803 						"testUint64": 545665757
    804 					}`,
    805 			expectedResult: testObject0Keys{},
    806 			err:            true,
    807 		},
    808 		{
    809 			name: "basic-err-uint32",
    810 			json: `{
    811 						"testStr": "hello world!",
    812 						"testInt": 4535,
    813 						"testBool": true,
    814 						"testFloat32": 2.345,
    815 						"testFloat64": 123.677,
    816 						"testInt8": 23,
    817 						"testInt16": 1245,
    818 						"testInt32": 456778,
    819 						"testInt64": 1446685358,
    820 						"testUint8": 255,
    821 						"testUint16": 3455,
    822 						"testUint32": 3x43443,
    823 						"testUint64": 545665757
    824 					}`,
    825 			expectedResult: testObject0Keys{},
    826 			err:            true,
    827 		},
    828 		{
    829 			name: "basic-err-uint64",
    830 			json: `{
    831 						"testStr": "hello world!",
    832 						"testInt": 4535,
    833 						"testBool": true,
    834 						"testFloat32": 2.345,
    835 						"testFloat64": 123.677,
    836 						"testInt8": 23,
    837 						"testInt16": 1245,
    838 						"testInt32": 456778,
    839 						"testInt64": 1446685358,
    840 						"testUint8": 255,
    841 						"testUint16": 3455,
    842 						"testUint32": 343443,
    843 						"testUint64": 5456x65757
    844 					}`,
    845 			expectedResult: testObject0Keys{},
    846 			err:            true,
    847 		},
    848 		{
    849 			name: "basic-skip-data",
    850 			json: `{
    851 				"testStr": "hello world!",
    852 				"testInt": 4535,
    853 				"testBool": true,
    854 				"testFloat32": 2.345,
    855 				"testFloat64": 123.677,
    856 				"testInt8": 23,
    857 				"skipObject": {
    858 					"escapedString": "string with escaped \\n new line"
    859 				},
    860 				"testInt16": 1245,
    861 				"testInt32": 456778,
    862 				"testInt64": 1446685358,
    863 				"testUint8": 255,
    864 				"skipArray": [[],[],{}],
    865 				"testUint16": 3455,
    866 				"skipBool": true,
    867 				"skipNull": null,
    868 				"testUint32": 343443,
    869 				"testUint64": 545665757,
    870 				"skipString": "skipping string with escaped \\n new line",
    871 				"skipInt": 3,
    872 			}`,
    873 			expectedResult: testObject0Keys{
    874 				testStr:     "hello world!",
    875 				testInt:     4535,
    876 				testBool:    true,
    877 				testFloat32: 2.345,
    878 				testFloat64: 123.677,
    879 				testInt8:    23,
    880 				testInt16:   1245,
    881 				testInt32:   456778,
    882 				testInt64:   1446685358,
    883 				testUint8:   255,
    884 				testUint16:  3455,
    885 				testUint32:  343443,
    886 				testUint64:  545665757,
    887 			},
    888 			err: false,
    889 		},
    890 	}
    891 
    892 	for _, testCase := range testCases {
    893 		t.Run(testCase.name, func(t *testing.T) {
    894 			s := testObject0Keys{}
    895 			dec := BorrowDecoder(strings.NewReader(testCase.json))
    896 			defer dec.Release()
    897 			err := dec.Decode(&s)
    898 			if testCase.err {
    899 				t.Log(err)
    900 				assert.NotNil(t, err, "err should not be nil")
    901 				if testCase.errType != nil {
    902 					assert.IsType(t, testCase.errType, err, "err should be of the given type")
    903 				}
    904 				return
    905 			}
    906 			assert.Nil(t, err, "err should be nil")
    907 			if !testCase.skipCheckResult {
    908 				assert.Equal(t, testCase.expectedResult, s, "value at given index should be the same as expected results")
    909 			}
    910 		})
    911 	}
    912 	for _, testCase := range testCases {
    913 		t.Run(testCase.name, func(t *testing.T) {
    914 			s := testObject0Keys{}
    915 			err := UnmarshalJSONObject([]byte(testCase.json), &s)
    916 			if testCase.err {
    917 				t.Log(err)
    918 				assert.NotNil(t, err, "err should not be nil")
    919 				if testCase.errType != nil {
    920 					assert.IsType(t, testCase.errType, err, "err should be of the given type")
    921 				}
    922 				return
    923 			}
    924 			assert.Nil(t, err, "err should be nil")
    925 			if !testCase.skipCheckResult {
    926 				assert.Equal(t, testCase.expectedResult, s, "value at given index should be the same as expected results")
    927 			}
    928 		})
    929 	}
    930 }
    931 
    932 type ObjectNull struct {
    933 	SubObject *ObjectNull
    934 	SubArray  *testSliceBools
    935 }
    936 
    937 func (o *ObjectNull) UnmarshalJSONObject(dec *Decoder, k string) error {
    938 	switch k {
    939 	case "subobject":
    940 		return dec.ObjectNull(&o.SubObject)
    941 	case "subarray":
    942 		return dec.AddArrayNull(&o.SubArray)
    943 	}
    944 	return nil
    945 }
    946 
    947 func (o *ObjectNull) NKeys() int {
    948 	return 2
    949 }
    950 
    951 type ObjectNullZeroNKeys struct {
    952 	SubObject *ObjectNullZeroNKeys
    953 	SubArray  *testSliceBools
    954 }
    955 
    956 func (o *ObjectNullZeroNKeys) UnmarshalJSONObject(dec *Decoder, k string) error {
    957 	switch k {
    958 	case "subobject":
    959 		return dec.AddObjectNull(&o.SubObject)
    960 	case "subarray":
    961 		return dec.AddArrayNull(&o.SubArray)
    962 	}
    963 	return nil
    964 }
    965 
    966 func (o *ObjectNullZeroNKeys) NKeys() int {
    967 	return 0
    968 }
    969 
    970 func TestDecodeObjectNull(t *testing.T) {
    971 	t.Run("sub obj should not be nil", func(t *testing.T) {
    972 		var o = &ObjectNull{}
    973 		var err = UnmarshalJSONObject([]byte(`{"subobject": {},"subarray":[true]}`), o)
    974 		assert.Nil(t, err)
    975 		assert.NotNil(t, o.SubObject)
    976 		assert.NotNil(t, o.SubArray)
    977 	})
    978 	t.Run("sub obj and sub array should be nil", func(t *testing.T) {
    979 		var o = &ObjectNull{}
    980 		var err = UnmarshalJSONObject([]byte(`{"subobject": null,"subarray": null}`), o)
    981 		assert.Nil(t, err)
    982 		assert.Nil(t, o.SubObject)
    983 		assert.Nil(t, o.SubArray)
    984 	})
    985 	t.Run(
    986 		"sub obj should not be be nil",
    987 		func(t *testing.T) {
    988 			var o = &ObjectNull{}
    989 			var err = UnmarshalJSONObject([]byte(`{"subobject":{"subobject":{}}}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
    990 				return dec.ObjectNull(&o.SubObject)
    991 			}))
    992 			assert.Nil(t, err)
    993 			assert.NotNil(t, o.SubObject)
    994 		},
    995 	)
    996 	t.Run(
    997 		"sub obj should be nil",
    998 		func(t *testing.T) {
    999 			var o = &ObjectNull{}
   1000 			var err = UnmarshalJSONObject([]byte(`{"subobject":null}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1001 				return dec.ObjectNull(&o.SubObject)
   1002 			}))
   1003 			assert.Nil(t, err)
   1004 			assert.Nil(t, o.SubObject)
   1005 		},
   1006 	)
   1007 	t.Run(
   1008 		"skip data",
   1009 		func(t *testing.T) {
   1010 			var o = &ObjectNull{}
   1011 			var err = UnmarshalJSONObject([]byte(`{
   1012 				"subobject": {
   1013 					"subobject": {},
   1014 					"subarray": [],
   1015 					"subarray": [],
   1016 					"skipped": ""
   1017 				}
   1018 			}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1019 				return dec.ObjectNull(&o.SubObject)
   1020 			}))
   1021 			assert.Nil(t, err)
   1022 			assert.NotNil(t, o.SubObject)
   1023 			assert.Nil(t, o.SubArray)
   1024 		},
   1025 	)
   1026 	t.Run(
   1027 		"skip data not child",
   1028 		func(t *testing.T) {
   1029 			var o = &ObjectNull{}
   1030 			var dec = NewDecoder(strings.NewReader(`{
   1031 					"subobject": {},
   1032 					"subarray": [],
   1033 					"subarray": [],
   1034 					"skipped": ""
   1035 			}`))
   1036 			var _, err = dec.decodeObjectNull(&o)
   1037 			assert.Nil(t, err)
   1038 			assert.NotNil(t, o.SubObject)
   1039 		},
   1040 	)
   1041 	t.Run(
   1042 		"err empty json",
   1043 		func(t *testing.T) {
   1044 			var o = &ObjectNull{}
   1045 			var dec = NewDecoder(strings.NewReader(``))
   1046 			var _, err = dec.decodeObjectNull(&o)
   1047 			assert.NotNil(t, err)
   1048 		},
   1049 	)
   1050 	t.Run(
   1051 		"should return an error as type is not ptr",
   1052 		func(t *testing.T) {
   1053 			var err = UnmarshalJSONObject([]byte(`{"key":{}}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1054 				return dec.ObjectNull("")
   1055 			}))
   1056 			assert.NotNil(t, err)
   1057 			assert.Equal(t, ErrUnmarshalPtrExpected, err)
   1058 		},
   1059 	)
   1060 	t.Run(
   1061 		"should return an error as type is not ptr",
   1062 		func(t *testing.T) {
   1063 			var err = UnmarshalJSONObject([]byte(`{"key":[]}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1064 				return dec.ArrayNull("")
   1065 			}))
   1066 			assert.NotNil(t, err)
   1067 			assert.Equal(t, ErrUnmarshalPtrExpected, err)
   1068 		},
   1069 	)
   1070 	t.Run(
   1071 		"should return an error as type is not ptr to UnmarshalerJSONObject",
   1072 		func(t *testing.T) {
   1073 			var err = UnmarshalJSONObject([]byte(`{"key":{}}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1074 				var strPtr = new(string)
   1075 				return dec.ObjectNull(&strPtr)
   1076 			}))
   1077 			assert.NotNil(t, err)
   1078 			assert.IsType(t, InvalidUnmarshalError(""), err)
   1079 		},
   1080 	)
   1081 	t.Run(
   1082 		"should return an error as type is not ptr to UnmarshalerJSONObject",
   1083 		func(t *testing.T) {
   1084 			var err = UnmarshalJSONObject([]byte(`{"key":[]}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1085 				var strPtr = new(string)
   1086 				return dec.ArrayNull(&strPtr)
   1087 			}))
   1088 			assert.NotNil(t, err)
   1089 			assert.IsType(t, InvalidUnmarshalError(""), err)
   1090 		},
   1091 	)
   1092 	t.Run(
   1093 		"should return an error as type is not ptr to UnmarshalerJSONObject",
   1094 		func(t *testing.T) {
   1095 			var err = UnmarshalJSONObject([]byte(`{"key":{}}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1096 				var strPtr = new(string)
   1097 				return dec.ArrayNull(&strPtr)
   1098 			}))
   1099 			assert.NotNil(t, err)
   1100 			assert.IsType(t, InvalidUnmarshalError(""), err)
   1101 		},
   1102 	)
   1103 	t.Run(
   1104 		"should return an error as type is not ptr to UnmarshalerJSONObject",
   1105 		func(t *testing.T) {
   1106 			var err = UnmarshalJSONObject([]byte(`{"key":"`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1107 				var strPtr = new(string)
   1108 				return dec.ArrayNull(&strPtr)
   1109 			}))
   1110 			assert.NotNil(t, err)
   1111 			assert.IsType(t, InvalidJSONError(""), err)
   1112 		},
   1113 	)
   1114 	t.Run(
   1115 		"skip data",
   1116 		func(t *testing.T) {
   1117 			var err = UnmarshalJSONObject([]byte(`{"key": ""}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1118 				var strPtr = new(string)
   1119 				return dec.ObjectNull(&strPtr)
   1120 			}))
   1121 			assert.NotNil(t, err)
   1122 			assert.IsType(t, InvalidUnmarshalError(""), err)
   1123 		},
   1124 	)
   1125 	t.Run(
   1126 		"invalid JSON for object",
   1127 		func(t *testing.T) {
   1128 			var o = &ObjectNull{}
   1129 			var err = UnmarshalJSONObject([]byte(`{"subobject":{"subobject":{"a":a}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1130 				return dec.ObjectNull(&o.SubObject)
   1131 			}))
   1132 			assert.NotNil(t, err)
   1133 			assert.IsType(t, InvalidJSONError(""), err)
   1134 		},
   1135 	)
   1136 	t.Run(
   1137 		"invalid JSON for object",
   1138 		func(t *testing.T) {
   1139 			var o = &ObjectNull{}
   1140 			var err = UnmarshalJSONObject([]byte(`{"subobject":{"subobject":a}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1141 				return dec.ObjectNull(&o.SubObject)
   1142 			}))
   1143 			assert.NotNil(t, err)
   1144 			assert.IsType(t, InvalidJSONError(""), err)
   1145 		},
   1146 	)
   1147 	t.Run(
   1148 		"invalid JSON for object",
   1149 		func(t *testing.T) {
   1150 			var o = &ObjectNull{}
   1151 			var err = UnmarshalJSONObject([]byte(`{"subobject":{"subobject":{"sub}}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1152 				return dec.ObjectNull(&o.SubObject)
   1153 			}))
   1154 			assert.NotNil(t, err)
   1155 			assert.IsType(t, InvalidJSONError(""), err)
   1156 		},
   1157 	)
   1158 	t.Run(
   1159 		"invalid JSON for object",
   1160 		func(t *testing.T) {
   1161 			var o = &testSliceBools{}
   1162 			var err = UnmarshalJSONObject([]byte(`{"subobject":a`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1163 				return dec.ArrayNull(&o)
   1164 			}))
   1165 			assert.NotNil(t, err)
   1166 			assert.IsType(t, InvalidJSONError(""), err)
   1167 		},
   1168 	)
   1169 	t.Run(
   1170 		"invalid JSON for object",
   1171 		func(t *testing.T) {
   1172 			var err = UnmarshalJSONObject([]byte(`{"key":a`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1173 				var strPtr = new(string)
   1174 				return dec.ObjectNull(&strPtr)
   1175 			}))
   1176 			assert.NotNil(t, err)
   1177 			assert.IsType(t, InvalidJSONError(""), err)
   1178 		},
   1179 	)
   1180 	t.Run(
   1181 		"invalid JSON for object",
   1182 		func(t *testing.T) {
   1183 			var err = UnmarshalJSONObject([]byte(`{"subobject": {},"}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1184 				var o = &ObjectNull{}
   1185 				return dec.ObjectNull(&o)
   1186 			}))
   1187 			assert.NotNil(t, err)
   1188 			assert.IsType(t, InvalidJSONError(""), err)
   1189 		},
   1190 	)
   1191 	t.Run(
   1192 		"invalid JSON for object",
   1193 		func(t *testing.T) {
   1194 			var o = &ObjectNull{}
   1195 			var err = UnmarshalJSONObject([]byte(`{"subobject": a`), o)
   1196 			assert.NotNil(t, err)
   1197 			assert.IsType(t, InvalidJSONError(""), err)
   1198 		},
   1199 	)
   1200 	t.Run(
   1201 		"invalid JSON for object",
   1202 		func(t *testing.T) {
   1203 			var o = &ObjectNull{}
   1204 			var err = UnmarshalJSONObject([]byte(`{"subobject": na`), o)
   1205 			assert.NotNil(t, err)
   1206 			assert.IsType(t, InvalidJSONError(""), err)
   1207 		},
   1208 	)
   1209 	t.Run(
   1210 		"zero nkeys, no error, two keys",
   1211 		func(t *testing.T) {
   1212 			var o = &ObjectNullZeroNKeys{}
   1213 			var err = UnmarshalJSONObject([]byte(`{
   1214 				"subobject": {
   1215 					"subobject": {
   1216 						"subobject":{}
   1217 					},
   1218 					"subarray": []
   1219 				}
   1220 			}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1221 				return dec.ObjectNull(&o.SubObject)
   1222 			}))
   1223 			assert.Nil(t, err)
   1224 		},
   1225 	)
   1226 	t.Run(
   1227 		"zero nkeys, no error, two keys, skip data",
   1228 		func(t *testing.T) {
   1229 			var o = &ObjectNullZeroNKeys{}
   1230 			var err = UnmarshalJSONObject([]byte(`{
   1231 				"subobject": {
   1232 					"subobject": {
   1233 						"subobject":{}
   1234 					},
   1235 					"subarray": [],
   1236 					"skipped": 1
   1237 				}
   1238 			}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1239 				return dec.ObjectNull(&o.SubObject)
   1240 			}))
   1241 			assert.Nil(t, err)
   1242 		},
   1243 	)
   1244 	t.Run(
   1245 		"zero nkeys, error skip data",
   1246 		func(t *testing.T) {
   1247 			var o = &ObjectNullZeroNKeys{}
   1248 			var err = UnmarshalJSONObject([]byte(`{
   1249 				"subobject": {
   1250 					"subobject": {
   1251 						"subobject":{}
   1252 					},
   1253 					"subarray": [],
   1254 					"skippedInvalid": "q
   1255 				}
   1256 			}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1257 				return dec.ObjectNull(&o.SubObject)
   1258 			}))
   1259 			assert.NotNil(t, err)
   1260 			assert.IsType(t, InvalidJSONError(""), err)
   1261 		},
   1262 	)
   1263 	t.Run(
   1264 		"zero nkeys, error invalid json in keys",
   1265 		func(t *testing.T) {
   1266 			var o = &ObjectNullZeroNKeys{}
   1267 			var err = UnmarshalJSONObject([]byte(`{
   1268 				"subobject": {
   1269 					"subobj
   1270 				}
   1271 			}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1272 				return dec.ObjectNull(&o.SubObject)
   1273 			}))
   1274 			assert.NotNil(t, err)
   1275 			assert.IsType(t, InvalidJSONError(""), err)
   1276 		},
   1277 	)
   1278 	t.Run(
   1279 		"zero nkeys, error invalid json, sub object",
   1280 		func(t *testing.T) {
   1281 			var o = &ObjectNullZeroNKeys{}
   1282 			var err = UnmarshalJSONObject([]byte(`{
   1283 				"subobject": {
   1284 					"subobject": {
   1285 						"subobj
   1286 					}	
   1287 				}
   1288 			}`), DecodeObjectFunc(func(dec *Decoder, k string) error {
   1289 				return dec.ObjectNull(&o.SubObject)
   1290 			}))
   1291 			assert.NotNil(t, err)
   1292 			assert.IsType(t, InvalidJSONError(""), err)
   1293 		},
   1294 	)
   1295 }
   1296 
   1297 func TestDecodeObjectComplex(t *testing.T) {
   1298 	testCases := []struct {
   1299 		name            string
   1300 		json            string
   1301 		expectedResult  testObjectComplex
   1302 		err             bool
   1303 		errType         interface{}
   1304 		skipCheckResult bool
   1305 	}{
   1306 		{
   1307 			name: "basic",
   1308 			json: `{
   1309 				"testSubObject": {},
   1310 				"testSubSliceInts": [1,2]
   1311 			}`,
   1312 			expectedResult: testObjectComplex{
   1313 				testSubObject:    &testObject{},
   1314 				testSubSliceInts: &testSliceInts{1, 2},
   1315 			},
   1316 			err: false,
   1317 		},
   1318 		{
   1319 			name: "complex",
   1320 			json: `{
   1321 				"testSubObject": {
   1322 					"testStr": "some string",
   1323 					"testInt":124465,
   1324 					"testUint16":120,
   1325 					"testUint8":15,
   1326 					"testInt16":-135,
   1327 					"testInt8":-23
   1328 				},
   1329 				"testSubSliceInts": [1,2,3,4,5],
   1330 				"testStr": "some \n string"
   1331 			}`,
   1332 			expectedResult: testObjectComplex{
   1333 				testSubObject: &testObject{
   1334 					testStr:    "some string",
   1335 					testInt:    124465,
   1336 					testUint16: 120,
   1337 					testUint8:  15,
   1338 					testInt16:  -135,
   1339 					testInt8:   -23,
   1340 				},
   1341 				testSubSliceInts: &testSliceInts{1, 2, 3, 4, 5},
   1342 				testStr:          "some \n string",
   1343 			},
   1344 			err: false,
   1345 		},
   1346 		{
   1347 			name: "complex-json-err",
   1348 			json: `{"testSubObject":{"testStr":"some string,"testInt":124465,"testUint16":120, "testUint8":15,"testInt16":-135,"testInt8":-23},"testSubSliceInts":[1,2],"testStr":"some \n string"}`,
   1349 			expectedResult: testObjectComplex{
   1350 				testSubObject: &testObject{},
   1351 			},
   1352 			err: true,
   1353 		},
   1354 	}
   1355 
   1356 	for _, testCase := range testCases {
   1357 		t.Run(testCase.name, func(t *testing.T) {
   1358 			s := testObjectComplex{
   1359 				testSubObject:    &testObject{},
   1360 				testSubSliceInts: &testSliceInts{},
   1361 			}
   1362 			dec := BorrowDecoder(strings.NewReader(testCase.json))
   1363 			defer dec.Release()
   1364 			err := dec.Decode(&s)
   1365 			if testCase.err {
   1366 				t.Log(err)
   1367 				assert.NotNil(t, err, "err should not be nil")
   1368 				if testCase.errType != nil {
   1369 					assert.IsType(t, testCase.errType, err, "err should be of the given type")
   1370 				}
   1371 				return
   1372 			}
   1373 			assert.Nil(t, err, "err should be nil")
   1374 			if !testCase.skipCheckResult {
   1375 				assert.Equal(t, testCase.expectedResult, s, "value at given index should be the same as expected results")
   1376 			}
   1377 		})
   1378 	}
   1379 }
   1380 
   1381 func assertResult(t *testing.T, v *TestObj, err error) {
   1382 	assert.Nil(t, err, "Err must be nil")
   1383 	assert.Equal(t, 245, v.test, "v.test must be equal to 245")
   1384 	assert.Equal(t, 246, v.test2, "v.test2 must be equal to 246")
   1385 	assert.Equal(t, "string", v.test3, "v.test3 must be equal to 'string'")
   1386 	assert.Equal(t, "complex string with spaces and some slashes\"", v.test4, "v.test4 must be equal to 'string'")
   1387 	assert.Equal(t, -1.15657654376543, v.test5, "v.test5 must be equal to 1.15")
   1388 	assert.Len(t, v.testArr, 2, "v.testArr must be of len 2")
   1389 
   1390 	assert.Equal(t, 121, v.testSubObj.test3, "v.testSubObj.test3 must be equal to 121")
   1391 	assert.Equal(t, 122, v.testSubObj.test4, "v.testSubObj.test4 must be equal to 122")
   1392 	assert.Equal(t, "string", v.testSubObj.test5, "v.testSubObj.test5 must be equal to 'string'")
   1393 	assert.Equal(t, 150, v.testSubObj.testSubSubObj.test3, "v.testSubObj.testSubSubObj.test3 must be equal to 150")
   1394 	assert.Equal(t, 150, v.testSubObj.testSubSubObj2.test3, "v.testSubObj.testSubSubObj2.test3 must be equal to 150")
   1395 
   1396 	assert.Equal(t, 122, v.testSubObj2.test3, "v.testSubObj2.test3 must be equal to 121")
   1397 	assert.Equal(t, 123, v.testSubObj2.test4, "v.testSubObj2.test4 must be equal to 122")
   1398 	assert.Equal(t, "string", v.testSubObj2.test5, "v.testSubObj2.test5 must be equal to 'string'")
   1399 	assert.Equal(t, 151, v.testSubObj2.testSubSubObj.test3, "v.testSubObj2.testSubSubObj.test must be equal to 150")
   1400 }
   1401 
   1402 func TestDecoderObject(t *testing.T) {
   1403 	json := []byte(`{
   1404 		"test": 245,
   1405 		"test2": 246,
   1406 		"test3": "string",
   1407 		"test4": "complex string with spaces and some slashes\"",
   1408 		"test5": -1.15657654376543,
   1409 		"testNull": null,
   1410 		"testArr": [
   1411 			{
   1412 				"test": 245,
   1413 				"test2": 246
   1414 			},
   1415 			{
   1416 				"test": 245,
   1417 				"test2": 246
   1418 			}
   1419 		],
   1420 		"testSubObj": {
   1421 			"test": 121,
   1422 			"test2": 122,
   1423 			"testNull": null,
   1424 			"testSubSubObj": {
   1425 				"test": 150,
   1426 				"testNull": null
   1427 			},
   1428 			"testSubSubObj2": {
   1429 				"test": 150
   1430 			},
   1431 			"test3": "string"
   1432 			"testNull": null,
   1433 		},
   1434 		"testSubObj2": {
   1435 			"test": 122,
   1436 			"test3": "string"
   1437 			"testSubSubObj": {
   1438 				"test": 151
   1439 			},
   1440 			"test2": 123
   1441 		}
   1442 	}`)
   1443 	v := &TestObj{}
   1444 	err := Unmarshal(json, v)
   1445 	assertResult(t, v, err)
   1446 }
   1447 
   1448 func TestDecodeObjectJSONNull(t *testing.T) {
   1449 	json := []byte(`null`)
   1450 	v := &TestObj{}
   1451 	err := Unmarshal(json, v)
   1452 	assert.Nil(t, err, "Err must be nil")
   1453 	assert.Equal(t, v.test, 0, "v.test must be 0 val")
   1454 }
   1455 
   1456 var jsonComplex = []byte(`{
   1457 	"test": "{\"test\":\"1\",\"test1\":2}",
   1458 	"test2\n": "\\\\\\\\\n",
   1459 	"testArrSkip": ["testString with escaped \\\" quotes"],
   1460 	"testSkipString": "skip \\ string with \n escaped char \" ",
   1461 	"testSkipObject": {
   1462 		"testSkipSubObj": {
   1463 			"test": "test"
   1464 		}
   1465 	},
   1466 	"testSkipNumber": 123.23,
   1467 	"testSkipNumber2": 123.23 ,
   1468 	"testBool": true,
   1469 	"testSkipBoolTrue": true,
   1470 	"testSkipBoolFalse": false,
   1471 	"testSkipBoolNull": null,
   1472 	"testSub": {
   1473 		"test": "{\"test\":\"1\",\"test1\":2}",
   1474 		"test2\n": "[1,2,3]",
   1475 		"test3": 1,
   1476 		"testObjSkip": {
   1477 			"test": "test string with escaped \" quotes"
   1478 		},
   1479 		"testStrSkip" : "test"
   1480 	},
   1481 	"testBoolSkip": false,
   1482 	"testObjInvalidType": "somestring",
   1483 	"testArrSkip2": [[],["someString"]],
   1484 	"test3": 1
   1485 }`)
   1486 
   1487 type jsonObjectComplex struct {
   1488 	Test               string
   1489 	Test2              string
   1490 	Test3              int
   1491 	Test4              bool
   1492 	testSub            *jsonObjectComplex
   1493 	testObjInvalidType *jsonObjectComplex
   1494 }
   1495 
   1496 func (j *jsonObjectComplex) UnmarshalJSONObject(dec *Decoder, key string) error {
   1497 	switch key {
   1498 	case "test":
   1499 		return dec.AddString(&j.Test)
   1500 	case "test2\n":
   1501 		return dec.AddString(&j.Test2)
   1502 	case "test3":
   1503 		return dec.AddInt(&j.Test3)
   1504 	case "testBool":
   1505 		return dec.AddBool(&j.Test4)
   1506 	case "testSub":
   1507 		j.testSub = &jsonObjectComplex{}
   1508 		return dec.AddObject(j.testSub)
   1509 	case "testObjInvalidType":
   1510 		j.testObjInvalidType = &jsonObjectComplex{}
   1511 		return dec.AddObject(j.testObjInvalidType)
   1512 	}
   1513 	return nil
   1514 }
   1515 
   1516 func (j *jsonObjectComplex) NKeys() int {
   1517 	return 6
   1518 }
   1519 
   1520 func TestDecodeObjComplex(t *testing.T) {
   1521 	result := jsonObjectComplex{}
   1522 	err := UnmarshalJSONObject(jsonComplex, &result)
   1523 	assert.NotNil(t, err, "err should not be as invalid type as been encountered nil")
   1524 	assert.Equal(t, `Cannot unmarshal JSON to type '*gojay.jsonObjectComplex'`, err.Error(), "err should not be as invalid type as been encountered nil")
   1525 	assert.Equal(t, `{"test":"1","test1":2}`, result.Test, "result.Test is not expected value")
   1526 	assert.Equal(t, "\\\\\\\\\n", result.Test2, "result.Test2 is not expected value")
   1527 	assert.Equal(t, 1, result.Test3, "result.test3 is not expected value")
   1528 	assert.Equal(t, `{"test":"1","test1":2}`, result.testSub.Test, "result.testSub.test is not expected value")
   1529 	assert.Equal(t, `[1,2,3]`, result.testSub.Test2, "result.testSub.test2 is not expected value")
   1530 	assert.Equal(t, 1, result.testSub.Test3, "result.testSub.test3 is not expected value")
   1531 	assert.Equal(t, true, result.Test4, "result.Test4 is not expected value, should be true")
   1532 }
   1533 
   1534 type jsonDecodePartial struct {
   1535 	Test  string
   1536 	Test2 string
   1537 }
   1538 
   1539 func (j *jsonDecodePartial) UnmarshalJSONObject(dec *Decoder, key string) error {
   1540 	switch key {
   1541 	case "test":
   1542 		return dec.AddString(&j.Test)
   1543 	case `test2`:
   1544 		return dec.AddString(&j.Test2)
   1545 	}
   1546 	return nil
   1547 }
   1548 
   1549 func (j *jsonDecodePartial) NKeys() int {
   1550 	return 2
   1551 }
   1552 
   1553 func TestDecodeObjectPartial(t *testing.T) {
   1554 	result := jsonDecodePartial{}
   1555 	dec := NewDecoder(nil)
   1556 	dec.data = []byte(`{
   1557 		"test": "test",
   1558 		"test2": "test",
   1559 		"testArrSkip": ["test"],
   1560 		"testSkipString": "test",
   1561 		"testSkipNumber": 123.23
   1562 	}`)
   1563 	dec.length = len(dec.data)
   1564 	err := dec.DecodeObject(&result)
   1565 	assert.Nil(t, err, "err should be nil")
   1566 	assert.NotEqual(t, len(dec.data), dec.cursor)
   1567 }
   1568 
   1569 func TestDecoderObjectInvalidJSON(t *testing.T) {
   1570 	result := jsonDecodePartial{}
   1571 	dec := NewDecoder(nil)
   1572 	dec.data = []byte(`{
   1573 		"test2": "test",
   1574 		"testArrSkip": ["test"],
   1575 		"testSkipString": "testInvalidJSON\\\\
   1576 	}`)
   1577 	dec.length = len(dec.data)
   1578 	err := dec.DecodeObject(&result)
   1579 	assert.NotNil(t, err, "Err must not be nil as JSON is invalid")
   1580 	assert.IsType(t, InvalidJSONError(""), err, "err message must be 'Invalid JSON'")
   1581 }
   1582 
   1583 type myMap map[string]string
   1584 
   1585 func (m myMap) UnmarshalJSONObject(dec *Decoder, k string) error {
   1586 	str := ""
   1587 	err := dec.AddString(&str)
   1588 	if err != nil {
   1589 		return err
   1590 	}
   1591 	m[k] = str
   1592 	return nil
   1593 }
   1594 
   1595 // return 0 to parse all keys
   1596 func (m myMap) NKeys() int {
   1597 	return 0
   1598 }
   1599 
   1600 func TestDecoderObjectMap(t *testing.T) {
   1601 	json := `{
   1602 		"test": "string",
   1603 		"test2": "string",
   1604 		"test3": "string",
   1605 		"test4": "string",
   1606 		"test5": "string",
   1607 	}`
   1608 	m := myMap(make(map[string]string))
   1609 	dec := BorrowDecoder(strings.NewReader(json))
   1610 	err := dec.Decode(m)
   1611 
   1612 	assert.Nil(t, err, "err should be nil")
   1613 	assert.Len(t, m, 5, "len of m should be 5")
   1614 }
   1615 
   1616 func TestDecoderObjectDecoderAPI(t *testing.T) {
   1617 	json := `{
   1618 		"test": 245,
   1619 		"test2": 246,
   1620 		"test3": "string",
   1621 		"test4": "complex string with spaces and some slashes\"",
   1622 		"test5": -1.15657654376543,
   1623 		"testNull": null,
   1624 		"testArr": [
   1625 			{
   1626 				"test": 245,
   1627 				"test2": 246
   1628 			},
   1629 			{
   1630 				"test": 245,
   1631 				"test2": 246
   1632 			}
   1633 		],
   1634 		"testSubObj": {
   1635 			"test": 121,
   1636 			"test2": 122,
   1637 			"testNull": null,
   1638 			"testSubSubObj": {
   1639 				"test": 150,
   1640 				"testNull": null
   1641 			},
   1642 			"testSubSubObj2": {
   1643 				"test": 150
   1644 			},
   1645 			"test3": "string"
   1646 			"testNull": null,
   1647 		},
   1648 		"testSubObj2": {
   1649 			"test": 122,
   1650 			"test3": "string"
   1651 			"testSubSubObj": {
   1652 				"test": 151
   1653 			},
   1654 			"test2": 123
   1655 		}
   1656 	}`
   1657 	v := &TestObj{}
   1658 	dec := NewDecoder(strings.NewReader(json))
   1659 	err := dec.DecodeObject(v)
   1660 	assertResult(t, v, err)
   1661 }
   1662 
   1663 type ReadCloser struct {
   1664 	json []byte
   1665 }
   1666 
   1667 func (r *ReadCloser) Read(b []byte) (int, error) {
   1668 	copy(b, r.json)
   1669 	return len(r.json), io.EOF
   1670 }
   1671 
   1672 func TestDecoderObjectDecoderAPIReadCloser(t *testing.T) {
   1673 	readCloser := ReadCloser{
   1674 		json: []byte(`{
   1675 			"test": "string",
   1676 			"test2": "string",
   1677 			"test3": "string",
   1678 			"test4": "string",
   1679 			"test5": "string",
   1680 		}`),
   1681 	}
   1682 	m := myMap(make(map[string]string))
   1683 	dec := NewDecoder(&readCloser)
   1684 	err := dec.DecodeObject(m)
   1685 	assert.Nil(t, err, "err should be nil")
   1686 	assert.Len(t, m, 5, "len of m should be 5")
   1687 }
   1688 
   1689 func TestDecoderObjectDecoderAPIFuncReadCloser(t *testing.T) {
   1690 	readCloser := ReadCloser{
   1691 		json: []byte(`{
   1692 			"test": "string",
   1693 			"test2": "string",
   1694 			"test3": "string",
   1695 			"test4": "string",
   1696 			"test5": "string",
   1697 		}`),
   1698 	}
   1699 	m := myMap(make(map[string]string))
   1700 	dec := NewDecoder(&readCloser)
   1701 	err := dec.DecodeObject(DecodeObjectFunc(func(dec *Decoder, k string) error {
   1702 		str := ""
   1703 		err := dec.AddString(&str)
   1704 		if err != nil {
   1705 			return err
   1706 		}
   1707 		m[k] = str
   1708 		return nil
   1709 	}))
   1710 	assert.Nil(t, err, "err should be nil")
   1711 	assert.Len(t, m, 5, "len of m should be 5")
   1712 }
   1713 
   1714 func TestDecoderObjectDecoderInvalidJSONError(t *testing.T) {
   1715 	v := &TestObj{}
   1716 	dec := NewDecoder(strings.NewReader(`{"err:}`))
   1717 	err := dec.DecodeObject(v)
   1718 	assert.NotNil(t, err, "Err must not be nil as JSON is invalid")
   1719 	assert.IsType(t, InvalidJSONError(""), err, "err message must be 'Invalid JSON'")
   1720 }
   1721 
   1722 func TestDecoderObjectDecoderInvalidJSONError2(t *testing.T) {
   1723 	v := &TestSubObj{}
   1724 	dec := NewDecoder(strings.NewReader(`{"err:}`))
   1725 	err := dec.DecodeObject(v)
   1726 	assert.NotNil(t, err, "Err must not be nil as JSON is invalid")
   1727 	assert.IsType(t, InvalidJSONError(""), err, "err message must be 'Invalid JSON'")
   1728 }
   1729 
   1730 func TestDecoderObjectDecoderInvalidJSONError3(t *testing.T) {
   1731 	v := &TestSubObj{}
   1732 	dec := NewDecoder(strings.NewReader(`{"err":"test}`))
   1733 	err := dec.DecodeObject(v)
   1734 	assert.NotNil(t, err, "Err must not be nil as JSON is invalid")
   1735 	assert.IsType(t, InvalidJSONError(""), err, "err message must be 'Invalid JSON'")
   1736 }
   1737 
   1738 func TestDecoderObjectDecoderInvalidJSONError4(t *testing.T) {
   1739 	testArr := testSliceInts{}
   1740 	dec := NewDecoder(strings.NewReader(`hello`))
   1741 	err := dec.DecodeArray(&testArr)
   1742 	assert.NotNil(t, err, "Err must not be nil as JSON is invalid")
   1743 	assert.IsType(t, InvalidJSONError(""), err, "err message must be 'Invalid JSON'")
   1744 }
   1745 
   1746 func TestDecoderObjectPoolError(t *testing.T) {
   1747 	result := jsonDecodePartial{}
   1748 	dec := NewDecoder(nil)
   1749 	dec.Release()
   1750 	defer func() {
   1751 		err := recover()
   1752 		assert.NotNil(t, err, "err shouldnt be nil")
   1753 		assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
   1754 	}()
   1755 	_ = dec.DecodeObject(&result)
   1756 	assert.True(t, false, "should not be called as decoder should have panicked")
   1757 }
   1758 
   1759 func TestNextKey(t *testing.T) {
   1760 	testCases := []struct {
   1761 		name          string
   1762 		json          string
   1763 		expectedValue string
   1764 		err           bool
   1765 	}{
   1766 		{
   1767 			name:          "basic",
   1768 			json:          `"key":"value"`,
   1769 			expectedValue: "key",
   1770 		},
   1771 		{
   1772 			name:          "basic-err",
   1773 			json:          ``,
   1774 			expectedValue: "",
   1775 			err:           true,
   1776 		},
   1777 		{
   1778 			name:          "basic-err2",
   1779 			json:          `"key"`,
   1780 			expectedValue: "",
   1781 			err:           true,
   1782 		},
   1783 		{
   1784 			name:          "basic-err3",
   1785 			json:          `"key`,
   1786 			expectedValue: "",
   1787 			err:           true,
   1788 		},
   1789 	}
   1790 	for _, testCase := range testCases {
   1791 		t.Run(testCase.name, func(t *testing.T) {
   1792 			dec := BorrowDecoder(strings.NewReader(testCase.json))
   1793 			s, _, err := dec.nextKey()
   1794 			if testCase.err {
   1795 				assert.NotNil(t, err, "err should not be nil")
   1796 				return
   1797 			}
   1798 			assert.Nil(t, err, "err should be nil")
   1799 			assert.Equal(t, testCase.expectedValue, s, fmt.Sprintf("s should be '%s'", testCase.expectedValue))
   1800 		})
   1801 	}
   1802 }
   1803 
   1804 func TestSkipObject(t *testing.T) {
   1805 	testCases := []struct {
   1806 		name string
   1807 		json string
   1808 		err  bool
   1809 	}{
   1810 		{
   1811 			name: "basic",
   1812 			json: `"key":"value"}`,
   1813 		},
   1814 		{
   1815 			name: "basic-escape-solidus",
   1816 			json: `"key":"value\/solidus"}`,
   1817 		},
   1818 		{
   1819 			name: "basic-escaped",
   1820 			json: `"key":"value\\\\\\\" hello"}`,
   1821 		},
   1822 		{
   1823 			name: "basic-escaped",
   1824 			json: `"key":"value\\\\\\\\"}`,
   1825 		},
   1826 		{
   1827 			name: "basic-err",
   1828 			json: ``,
   1829 			err:  true,
   1830 		},
   1831 		{
   1832 			name: "basic-err2",
   1833 			json: `{"key":"value"`,
   1834 			err:  true,
   1835 		},
   1836 		{
   1837 			name: "basic-err2",
   1838 			json: `"key":"value\n"}`,
   1839 			err:  false,
   1840 		},
   1841 	}
   1842 	for _, testCase := range testCases {
   1843 		t.Run(testCase.name, func(t *testing.T) {
   1844 			dec := BorrowDecoder(strings.NewReader(testCase.json))
   1845 			defer dec.Release()
   1846 			_, err := dec.skipObject()
   1847 			if testCase.err {
   1848 				assert.NotNil(t, err, "err should not be nil")
   1849 				return
   1850 			}
   1851 			assert.Nil(t, err, "err should be nil")
   1852 		})
   1853 	}
   1854 }
   1855 
   1856 func TestSkipData(t *testing.T) {
   1857 	testCases := []struct {
   1858 		name string
   1859 		err  bool
   1860 		json string
   1861 	}{
   1862 		{
   1863 			name: "skip-bool-false-err",
   1864 			json: `fulse`,
   1865 			err:  true,
   1866 		},
   1867 		{
   1868 			name: "skip-bool-true-err",
   1869 			json: `trou`,
   1870 			err:  true,
   1871 		},
   1872 		{
   1873 			name: "skip-bool-null-err",
   1874 			json: `nil`,
   1875 			err:  true,
   1876 		},
   1877 	}
   1878 
   1879 	for _, testCase := range testCases {
   1880 		t.Run(testCase.name, func(t *testing.T) {
   1881 			dec := NewDecoder(strings.NewReader(testCase.json))
   1882 			err := dec.skipData()
   1883 			if testCase.err {
   1884 				assert.NotNil(t, err, "err should not be nil")
   1885 			} else {
   1886 				assert.Nil(t, err, "err should be nil")
   1887 			}
   1888 		})
   1889 	}
   1890 	t.Run("error-invalid-json", func(t *testing.T) {
   1891 		dec := NewDecoder(strings.NewReader(""))
   1892 		err := dec.skipData()
   1893 		assert.NotNil(t, err, "err should not be nil as data is empty")
   1894 		assert.IsType(t, InvalidJSONError(""), err, "err should of type InvalidJSONError")
   1895 	})
   1896 	t.Run("skip-array-error-invalid-json", func(t *testing.T) {
   1897 		dec := NewDecoder(strings.NewReader(""))
   1898 		_, err := dec.skipArray()
   1899 		assert.NotNil(t, err, "err should not be nil as data is empty")
   1900 		assert.IsType(t, InvalidJSONError(""), err, "err should of type InvalidJSONError")
   1901 	})
   1902 }