commit 0c6779450769d47ded18c7c53a88e2889ed97bc0
parent c35963f96584327d30ee89005766d166d4b50626
Author: francoispqt <francois@parquet.ninja>
Date: Sat, 19 May 2018 22:11:41 +0800
add tests
Diffstat:
9 files changed, 708 insertions(+), 91 deletions(-)
diff --git a/decode_object.go b/decode_object.go
@@ -97,14 +97,13 @@ func (dec *Decoder) decodeObject(j UnmarshalerJSONObject) (int, error) {
return dec.cursor, nil
}
}
- return 0, dec.raiseInvalidJSONErr(dec.length - 1)
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) skipObject() (int, error) {
var objectsOpen = 1
var objectsClosed = 0
- // var stringOpen byte = 0
- for j := dec.cursor; j < dec.length; j++ {
+ for j := dec.cursor; j < dec.length || dec.read(); j++ {
switch dec.data[j] {
case '}':
objectsClosed++
@@ -117,7 +116,7 @@ func (dec *Decoder) skipObject() (int, error) {
objectsOpen++
case '"':
j++
- for ; j < dec.length; j++ {
+ for ; j < dec.length || dec.read(); j++ {
if dec.data[j] != '"' {
continue
}
@@ -127,7 +126,7 @@ func (dec *Decoder) skipObject() (int, error) {
// loop backward and count how many anti slash found
// to see if string is effectively escaped
ct := 1
- for i := j; i > 0; i-- {
+ for i := j - 1; i > 0; i-- {
if dec.data[i] != '\\' {
break
}
@@ -135,14 +134,14 @@ func (dec *Decoder) skipObject() (int, error) {
}
// is pair number of slashes, quote is not escaped
if ct&1 == 0 {
- break
+ continue
}
}
default:
continue
}
}
- return 0, nil
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) nextKey() (string, bool, error) {
@@ -177,7 +176,7 @@ func (dec *Decoder) nextKey() (string, bool, error) {
return "", false, dec.raiseInvalidJSONErr(dec.cursor)
}
}
- return "", false, dec.raiseInvalidJSONErr(dec.length - 1)
+ return "", false, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) skipData() error {
diff --git a/decode_object_test.go b/decode_object_test.go
@@ -1,6 +1,7 @@
package gojay
import (
+ "fmt"
"io"
"strings"
"testing"
@@ -52,6 +53,34 @@ func TestDecodeObjectBasic(t *testing.T) {
err: false,
},
{
+ name: "basic-err-invalid-type",
+ json: `1`,
+ expectedResult: testObject{},
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ {
+ name: "basic-err-invalid-json",
+ json: `hello`,
+ expectedResult: testObject{},
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-err-invalid-json",
+ json: `nall`,
+ expectedResult: testObject{},
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-err-invalid-type",
+ json: ``,
+ expectedResult: testObject{},
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
name: "basic-err",
json: `{
"testStr": "hello world!",
@@ -271,6 +300,48 @@ func TestDecodeObjectBasic(t *testing.T) {
expectedResult: testObject{},
err: true,
},
+ {
+ name: "basic-skip-data",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "skipObject": {
+ "escapedString": "string with escaped \\n new line"
+ },
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "skipArray": [[],[],{}],
+ "testUint16": 3455,
+ "skipBool": true,
+ "skipNull": null,
+ "testUint32": 343443,
+ "testUint64": 545665757,
+ "skipString": "skipping string with escaped \\n new line",
+ "skipInt": 3,
+ }`,
+ expectedResult: testObject{
+ testStr: "hello world!",
+ testInt: 4535,
+ testBool: true,
+ testFloat32: 2.345,
+ testFloat64: 123.677,
+ testInt8: 23,
+ testInt16: 1245,
+ testInt32: 456778,
+ testInt64: 1446685358,
+ testUint8: 255,
+ testUint16: 3455,
+ testUint32: 343443,
+ testUint64: 545665757,
+ },
+ err: false,
+ },
}
for _, testCase := range testCases {
@@ -295,6 +366,363 @@ func TestDecodeObjectBasic(t *testing.T) {
}
}
+func TestDecodeObjectBasic0Keys(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult testObject0Keys
+ err bool
+ errType interface{}
+ skipCheckResult bool
+ }{
+ {
+ name: "basic",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{
+ testStr: "hello world!",
+ testInt: 4535,
+ testBool: true,
+ testFloat32: 2.345,
+ testFloat64: 123.677,
+ testInt8: 23,
+ testInt16: 1245,
+ testInt32: 456778,
+ testInt64: 1446685358,
+ testUint8: 255,
+ testUint16: 3455,
+ testUint32: 343443,
+ testUint64: 545665757,
+ },
+ err: false,
+ },
+ {
+ name: "basic-err-invalid-type",
+ json: `1`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ {
+ name: "basic-err-invalid-json",
+ json: `hello`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-err-invalid-json",
+ json: `nall`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-err-invalid-type",
+ json: ``,
+ expectedResult: testObject0Keys{},
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-err",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 453q5,
+ "testBool": trae,
+ "testFloat32": 2q.345,
+ "testFloat64": 12x3.677,
+ "testInt8": 2s3,
+ "testInt16": 1245,
+ "testInt32": 4567q78,
+ "testInt64": 14466e85358,
+ "testUint8": 2s55,
+ "testUint16": 345i5,
+ "testUint32": 343q443,
+ "testUint64": 5456657z57
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err2",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 4567x78,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err-float32",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2q.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err-float64",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 1x23.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err3",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 2q3,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err-int16",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1x245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err-int64",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446q685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err-uint8",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 2x55,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err-uint16",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3x455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err-uint32",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 3x43443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-err-uint64",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 5456x65757
+ }`,
+ expectedResult: testObject0Keys{},
+ err: true,
+ },
+ {
+ name: "basic-skip-data",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "skipObject": {
+ "escapedString": "string with escaped \\n new line"
+ },
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "skipArray": [[],[],{}],
+ "testUint16": 3455,
+ "skipBool": true,
+ "skipNull": null,
+ "testUint32": 343443,
+ "testUint64": 545665757,
+ "skipString": "skipping string with escaped \\n new line",
+ "skipInt": 3,
+ }`,
+ expectedResult: testObject0Keys{
+ testStr: "hello world!",
+ testInt: 4535,
+ testBool: true,
+ testFloat32: 2.345,
+ testFloat64: 123.677,
+ testInt8: 23,
+ testInt16: 1245,
+ testInt32: 456778,
+ testInt64: 1446685358,
+ testUint8: 255,
+ testUint16: 3455,
+ testUint32: 343443,
+ testUint64: 545665757,
+ },
+ err: false,
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ s := testObject0Keys{}
+ dec := BorrowDecoder(strings.NewReader(testCase.json))
+ defer dec.Release()
+ err := dec.Decode(&s)
+ if testCase.err {
+ t.Log(err)
+ assert.NotNil(t, err, "err should not be nil")
+ if testCase.errType != nil {
+ assert.IsType(t, testCase.errType, err, "err should be of the given type")
+ }
+ return
+ }
+ assert.Nil(t, err, "err should be nil")
+ if !testCase.skipCheckResult {
+ assert.Equal(t, testCase.expectedResult, s, "value at given index should be the same as expected results")
+ }
+ })
+ }
+}
+
func TestDecodeObjectComplex(t *testing.T) {
testCases := []struct {
name string
@@ -306,7 +734,10 @@ func TestDecodeObjectComplex(t *testing.T) {
}{
{
name: "basic",
- json: `{"testSubObject":{},"testSubSliceInts":[1,2]}`,
+ json: `{
+ "testSubObject": {},
+ "testSubSliceInts": [1,2]
+ }`,
expectedResult: testObjectComplex{
testSubObject: &testObject{},
testSubSliceInts: &testSliceInts{1, 2},
@@ -315,7 +746,18 @@ func TestDecodeObjectComplex(t *testing.T) {
},
{
name: "complex",
- json: `{"testSubObject":{"testStr":"some string","testInt":124465,"testUint16":120, "testUint8":15,"testInt16":-135,"testInt8":-23},"testSubSliceInts":[1,2],"testStr":"some \\n string"}`,
+ json: `{
+ "testSubObject": {
+ "testStr": "some string",
+ "testInt":124465,
+ "testUint16":120,
+ "testUint8":15,
+ "testInt16":-135,
+ "testInt8":-23
+ },
+ "testSubSliceInts": [1,2,3,4,5],
+ "testStr": "some \\n string"
+ }`,
expectedResult: testObjectComplex{
testSubObject: &testObject{
testStr: "some string",
@@ -325,7 +767,7 @@ func TestDecodeObjectComplex(t *testing.T) {
testInt16: -135,
testInt8: -23,
},
- testSubSliceInts: &testSliceInts{1, 2},
+ testSubSliceInts: &testSliceInts{1, 2, 3, 4, 5},
testStr: "some \n string",
},
err: false,
@@ -365,75 +807,6 @@ func TestDecodeObjectComplex(t *testing.T) {
}
}
-type TestObj struct {
- test int
- test2 int
- test3 string
- test4 string
- test5 float64
- testArr testSliceObjects
- testSubObj *TestSubObj
- testSubObj2 *TestSubObj
-}
-
-type TestSubObj struct {
- test3 int
- test4 int
- test5 string
- testSubSubObj *TestSubObj
- testSubSubObj2 *TestSubObj
-}
-
-func (t *TestSubObj) UnmarshalJSONObject(dec *Decoder, key string) error {
- switch key {
- case "test":
- return dec.AddInt(&t.test3)
- case "test2":
- return dec.AddInt(&t.test4)
- case "test3":
- return dec.AddString(&t.test5)
- case "testSubSubObj":
- t.testSubSubObj = &TestSubObj{}
- return dec.AddObject(t.testSubSubObj)
- case "testSubSubObj2":
- t.testSubSubObj2 = &TestSubObj{}
- return dec.AddObject(t.testSubSubObj2)
- }
- return nil
-}
-
-func (t *TestSubObj) NKeys() int {
- return 0
-}
-
-func (t *TestObj) UnmarshalJSONObject(dec *Decoder, key string) error {
- switch key {
- case "test":
- return dec.AddInt(&t.test)
- case "test2":
- return dec.AddInt(&t.test2)
- case "test3":
- return dec.AddString(&t.test3)
- case "test4":
- return dec.AddString(&t.test4)
- case "test5":
- return dec.AddFloat(&t.test5)
- case "testSubObj":
- t.testSubObj = &TestSubObj{}
- return dec.AddObject(t.testSubObj)
- case "testSubObj2":
- t.testSubObj2 = &TestSubObj{}
- return dec.AddObject(t.testSubObj2)
- case "testArr":
- return dec.AddArray(&t.testArr)
- }
- return nil
-}
-
-func (t *TestObj) NKeys() int {
- return 8
-}
-
func assertResult(t *testing.T, v *TestObj, err error) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, 245, v.test, "v.test must be equal to 245")
@@ -442,10 +815,6 @@ func assertResult(t *testing.T, v *TestObj, err error) {
assert.Equal(t, "complex string with spaces and some slashes\"", v.test4, "v.test4 must be equal to 'string'")
assert.Equal(t, -1.15657654376543, v.test5, "v.test5 must be equal to 1.15")
assert.Len(t, v.testArr, 2, "v.testArr must be of len 2")
- // assert.Equal(t, v.testArr[0].test, 245, "v.testArr[0].test must be equal to 245")
- // assert.Equal(t, v.testArr[0].test2, 246, "v.testArr[0].test must be equal to 246")
- // assert.Equal(t, v.testArr[1].test, 245, "v.testArr[0].test must be equal to 245")
- // assert.Equal(t, v.testArr[1].test2, 246, "v.testArr[0].test must be equal to 246")
assert.Equal(t, 121, v.testSubObj.test3, "v.testSubObj.test3 must be equal to 121")
assert.Equal(t, 122, v.testSubObj.test4, "v.testSubObj.test4 must be equal to 122")
@@ -816,6 +1185,90 @@ func TestDecoderObjectPoolError(t *testing.T) {
assert.True(t, false, "should not be called as decoder should have panicked")
}
+func TestNextKey(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedValue string
+ err bool
+ }{
+ {
+ name: "basic",
+ json: `"key":"value"`,
+ expectedValue: "key",
+ },
+ {
+ name: "basic-err",
+ json: ``,
+ expectedValue: "",
+ err: true,
+ },
+ {
+ name: "basic-err2",
+ json: `"key"`,
+ expectedValue: "",
+ err: true,
+ },
+ {
+ name: "basic-err3",
+ json: `"key`,
+ expectedValue: "",
+ err: true,
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ dec := BorrowDecoder(strings.NewReader(testCase.json))
+ s, _, err := dec.nextKey()
+ if testCase.err {
+ assert.NotNil(t, err, "err should not be nil")
+ return
+ }
+ assert.Nil(t, err, "err should be nil")
+ assert.Equal(t, testCase.expectedValue, s, fmt.Sprintf("s should be '%s'", testCase.expectedValue))
+ })
+ }
+}
+
+func TestSkipObject(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ err bool
+ }{
+ {
+ name: "basic",
+ json: `"key":"value"}`,
+ },
+ {
+ name: "basic-escaped",
+ json: `"key":"value\\\\\\" hello"}`,
+ },
+ {
+ name: "basic-err",
+ json: ``,
+ err: true,
+ },
+ {
+ name: "basic-err2",
+ json: `{"key":"value"`,
+ err: true,
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ dec := BorrowDecoder(strings.NewReader(testCase.json))
+ defer dec.Release()
+ _, err := dec.skipObject()
+ if testCase.err {
+ assert.NotNil(t, err, "err should not be nil")
+ return
+ }
+ assert.Nil(t, err, "err should be nil")
+ })
+ }
+}
+
func TestSkipData(t *testing.T) {
testCases := []struct {
name string
diff --git a/decode_pool.go b/decode_pool.go
@@ -6,9 +6,7 @@ import (
)
var decPool = sync.Pool{
- New: func() interface{} {
- return NewDecoder(nil)
- },
+ New: newDecoderPool,
}
func init() {
@@ -31,6 +29,9 @@ func NewDecoder(r io.Reader) *Decoder {
isPooled: 0,
}
}
+func newDecoderPool() interface{} {
+ return NewDecoder(nil)
+}
// BorrowDecoder borrows a Decoder from the pool.
// It takes an io.Reader implementation as data input.
diff --git a/decode_pool_test.go b/decode_pool_test.go
@@ -10,3 +10,8 @@ func TestDecoderBorrowFromPoolSetBuffSize(t *testing.T) {
dec := borrowDecoder(nil, 512)
assert.Len(t, dec.data, 512, "data buffer should be of len 512")
}
+
+func TestDecoderNewPool(t *testing.T) {
+ dec := newDecoderPool()
+ assert.IsType(t, &Decoder{}, dec, "dec should be a *Decoder")
+}
diff --git a/decode_stream_pool.go b/decode_stream_pool.go
@@ -6,9 +6,7 @@ import (
)
var streamDecPool = sync.Pool{
- New: func() interface{} {
- return Stream.NewDecoder(nil)
- },
+ New: newStreamDecoderPool,
}
// NewDecoder returns a new StreamDecoder.
@@ -22,6 +20,9 @@ func (s stream) NewDecoder(r io.Reader) *StreamDecoder {
}
return streamDec
}
+func newStreamDecoderPool() interface{} {
+ return Stream.NewDecoder(nil)
+}
// BorrowDecoder borrows a StreamDecoder from the pool.
// It takes an io.Reader implementation as data input.
diff --git a/decode_stream_pool_test.go b/decode_stream_pool_test.go
@@ -51,3 +51,8 @@ func TestDecodeStreamDecodePooledDecoderError2(t *testing.T) {
// make sure they are the same
assert.True(t, false, "should not be called as decoder should have panicked")
}
+
+func TestStreamDecoderNewPool(t *testing.T) {
+ dec := newStreamDecoderPool()
+ assert.IsType(t, &StreamDecoder{}, dec, "dec should be a *StreamDecoder")
+}
diff --git a/decode_string.go b/decode_string.go
@@ -172,7 +172,7 @@ func (dec *Decoder) parseEscapedString() error {
}
}
}
- return nil
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getString() (int, int, error) {
diff --git a/decode_string_test.go b/decode_string_test.go
@@ -97,6 +97,12 @@ func TestDecoderString(t *testing.T) {
},
{
name: "escape-control-char",
+ json: `"\`,
+ expectedResult: "",
+ err: true,
+ },
+ {
+ name: "escape-control-char",
json: `"\\r"`,
expectedResult: "\r",
err: false,
diff --git a/gojay_test.go b/gojay_test.go
@@ -78,6 +78,84 @@ func (t *testObject) NKeys() int {
return 13
}
+type testObject0Keys struct {
+ testStr string
+ testInt int
+ testInt64 int64
+ testInt32 int32
+ testInt16 int16
+ testInt8 int8
+ testUint64 uint64
+ testUint32 uint32
+ testUint16 uint16
+ testUint8 uint8
+ testFloat64 float64
+ testFloat32 float32
+ testBool bool
+ testSubObject *testObject0Keys
+ testSubArray testSliceInts
+}
+
+// make sure it implements interfaces
+var _ MarshalerJSONObject = &testObject0Keys{}
+var _ UnmarshalerJSONObject = &testObject0Keys{}
+
+func (t *testObject0Keys) IsNil() bool {
+ return t == nil
+}
+
+func (t *testObject0Keys) MarshalJSONObject(enc *Encoder) {
+ enc.AddStringKey("testStr", t.testStr)
+ enc.AddIntKey("testInt", t.testInt)
+ enc.AddIntKey("testInt64", int(t.testInt64))
+ enc.AddIntKey("testInt32", int(t.testInt32))
+ enc.AddIntKey("testInt16", int(t.testInt16))
+ enc.AddIntKey("testInt8", int(t.testInt8))
+ enc.AddIntKey("testUint64", int(t.testUint64))
+ enc.AddIntKey("testUint32", int(t.testUint32))
+ enc.AddIntKey("testUint16", int(t.testUint16))
+ enc.AddIntKey("testUint8", int(t.testUint8))
+ enc.AddFloatKey("testFloat64", t.testFloat64)
+ enc.AddFloat32Key("testFloat32", t.testFloat32)
+ enc.AddBoolKey("testBool", t.testBool)
+}
+
+func (t *testObject0Keys) UnmarshalJSONObject(dec *Decoder, k string) error {
+ switch k {
+ case "testStr":
+ return dec.AddString(&t.testStr)
+ case "testInt":
+ return dec.AddInt(&t.testInt)
+ case "testInt64":
+ return dec.AddInt64(&t.testInt64)
+ case "testInt32":
+ return dec.AddInt32(&t.testInt32)
+ case "testInt16":
+ return dec.AddInt16(&t.testInt16)
+ case "testInt8":
+ return dec.AddInt8(&t.testInt8)
+ case "testUint64":
+ return dec.AddUint64(&t.testUint64)
+ case "testUint32":
+ return dec.AddUint32(&t.testUint32)
+ case "testUint16":
+ return dec.AddUint16(&t.testUint16)
+ case "testUint8":
+ return dec.AddUint8(&t.testUint8)
+ case "testFloat64":
+ return dec.AddFloat(&t.testFloat64)
+ case "testFloat32":
+ return dec.AddFloat32(&t.testFloat32)
+ case "testBool":
+ return dec.AddBool(&t.testBool)
+ }
+ return nil
+}
+
+func (t *testObject0Keys) NKeys() int {
+ return 0
+}
+
type testObjectComplex struct {
testSubObject *testObject
testSubSliceInts *testSliceInts
@@ -116,3 +194,72 @@ func (t *testObjectComplex) NKeys() int {
// make sure it implements interfaces
var _ MarshalerJSONObject = &testObjectComplex{}
var _ UnmarshalerJSONObject = &testObjectComplex{}
+
+type TestObj struct {
+ test int
+ test2 int
+ test3 string
+ test4 string
+ test5 float64
+ testArr testSliceObjects
+ testSubObj *TestSubObj
+ testSubObj2 *TestSubObj
+}
+
+type TestSubObj struct {
+ test3 int
+ test4 int
+ test5 string
+ testSubSubObj *TestSubObj
+ testSubSubObj2 *TestSubObj
+}
+
+func (t *TestSubObj) UnmarshalJSONObject(dec *Decoder, key string) error {
+ switch key {
+ case "test":
+ return dec.AddInt(&t.test3)
+ case "test2":
+ return dec.AddInt(&t.test4)
+ case "test3":
+ return dec.AddString(&t.test5)
+ case "testSubSubObj":
+ t.testSubSubObj = &TestSubObj{}
+ return dec.AddObject(t.testSubSubObj)
+ case "testSubSubObj2":
+ t.testSubSubObj2 = &TestSubObj{}
+ return dec.AddObject(t.testSubSubObj2)
+ }
+ return nil
+}
+
+func (t *TestSubObj) NKeys() int {
+ return 0
+}
+
+func (t *TestObj) UnmarshalJSONObject(dec *Decoder, key string) error {
+ switch key {
+ case "test":
+ return dec.AddInt(&t.test)
+ case "test2":
+ return dec.AddInt(&t.test2)
+ case "test3":
+ return dec.AddString(&t.test3)
+ case "test4":
+ return dec.AddString(&t.test4)
+ case "test5":
+ return dec.AddFloat(&t.test5)
+ case "testSubObj":
+ t.testSubObj = &TestSubObj{}
+ return dec.AddObject(t.testSubObj)
+ case "testSubObj2":
+ t.testSubObj2 = &TestSubObj{}
+ return dec.AddObject(t.testSubObj2)
+ case "testArr":
+ return dec.AddArray(&t.testArr)
+ }
+ return nil
+}
+
+func (t *TestObj) NKeys() int {
+ return 8
+}