Skip to content

Commit a2c156a

Browse files
authored
Merge pull request #59 from francoispqt/version/v1.2.0
Version/v1.2.0
2 parents f4c5a97 + 5902817 commit a2c156a

13 files changed

+2182
-151
lines changed

decode.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"io"
66
"reflect"
7+
"time"
78
)
89

910
// UnmarshalJSONArray parses the JSON-encoded data and stores the result in the value pointed to by v.
@@ -482,6 +483,21 @@ func (dec *Decoder) String(v *string) error {
482483
return nil
483484
}
484485

486+
// AddTime decodes the next key to a *time.Time with the given format
487+
func (dec *Decoder) AddTime(v *time.Time, format string) error {
488+
return dec.Time(v, format)
489+
}
490+
491+
// Time decodes the next key to a *time.Time with the given format
492+
func (dec *Decoder) Time(v *time.Time, format string) error {
493+
err := dec.decodeTime(v, format)
494+
if err != nil {
495+
return err
496+
}
497+
dec.called |= 1
498+
return nil
499+
}
500+
485501
// Object decodes the next key to a UnmarshalerJSONObject.
486502
func (dec *Decoder) Object(value UnmarshalerJSONObject) error {
487503
initialKeysDone := dec.keysDone

decode_array_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,12 @@ func TestSliceStrings(t *testing.T) {
112112
},
113113
{
114114
name: "basic-test",
115-
json: `["hello world", "hey" , "foo","bar \\n escape"]`,
115+
json: `["hello world", "hey" , "foo","bar \n escape"]`,
116116
expectedResult: testSliceStrings{"hello world", "hey", "foo", "bar \n escape"},
117117
},
118118
{
119119
name: "basic-test",
120-
json: `["hello world", "hey" , null,"bar \\n escape"]`,
120+
json: `["hello world", "hey" , null,"bar \n escape"]`,
121121
expectedResult: testSliceStrings{"hello world", "hey", "", "bar \n escape"},
122122
},
123123
{
@@ -534,6 +534,13 @@ func TestSkipArray(t *testing.T) {
534534
assert.Nil(t, err)
535535
},
536536
},
537+
{
538+
json: `"test \n"]`,
539+
expectations: func(t *testing.T, i int, err error) {
540+
assert.Equal(t, len(`"test \n"]`), i)
541+
assert.Nil(t, err)
542+
},
543+
},
537544
}
538545

539546
for _, test := range testCases {

decode_object_test.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -877,14 +877,14 @@ func TestDecodeObjectComplex(t *testing.T) {
877877
json: `{
878878
"testSubObject": {
879879
"testStr": "some string",
880-
"testInt":124465,
881-
"testUint16":120,
882-
"testUint8":15,
883-
"testInt16":-135,
880+
"testInt":124465,
881+
"testUint16":120,
882+
"testUint8":15,
883+
"testInt16":-135,
884884
"testInt8":-23
885885
},
886886
"testSubSliceInts": [1,2,3,4,5],
887-
"testStr": "some \\n string"
887+
"testStr": "some \n string"
888888
}`,
889889
expectedResult: testObjectComplex{
890890
testSubObject: &testObject{
@@ -902,7 +902,7 @@ func TestDecodeObjectComplex(t *testing.T) {
902902
},
903903
{
904904
name: "complex-json-err",
905-
json: `{"testSubObject":{"testStr":"some string,"testInt":124465,"testUint16":120, "testUint8":15,"testInt16":-135,"testInt8":-23},"testSubSliceInts":[1,2],"testStr":"some \\n string"}`,
905+
json: `{"testSubObject":{"testStr":"some string,"testInt":124465,"testUint16":120, "testUint8":15,"testInt16":-135,"testInt8":-23},"testSubSliceInts":[1,2],"testStr":"some \n string"}`,
906906
expectedResult: testObjectComplex{
907907
testSubObject: &testObject{},
908908
},
@@ -1012,9 +1012,9 @@ func TestDecodeObjectNull(t *testing.T) {
10121012

10131013
var jsonComplex = []byte(`{
10141014
"test": "{\"test\":\"1\",\"test1\":2}",
1015-
"test2\\n": "\\\\\\\\\\n",
1015+
"test2\n": "\\\\\\\\\n",
10161016
"testArrSkip": ["testString with escaped \\\" quotes"],
1017-
"testSkipString": "skip \\ string with \\n escaped char \" ",
1017+
"testSkipString": "skip \\ string with \n escaped char \" ",
10181018
"testSkipObject": {
10191019
"testSkipSubObj": {
10201020
"test": "test"
@@ -1028,7 +1028,7 @@ var jsonComplex = []byte(`{
10281028
"testSkipBoolNull": null,
10291029
"testSub": {
10301030
"test": "{\"test\":\"1\",\"test1\":2}",
1031-
"test2\\n": "[1,2,3]",
1031+
"test2\n": "[1,2,3]",
10321032
"test3": 1,
10331033
"testObjSkip": {
10341034
"test": "test string with escaped \" quotes"
@@ -1382,6 +1382,11 @@ func TestSkipObject(t *testing.T) {
13821382
json: `{"key":"value"`,
13831383
err: true,
13841384
},
1385+
{
1386+
name: "basic-err2",
1387+
json: `"key":"value\n"}`,
1388+
err: false,
1389+
},
13851390
}
13861391
for _, testCase := range testCases {
13871392
t.Run(testCase.name, func(t *testing.T) {

decode_sqlnull.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package gojay
2+
3+
import "database/sql"
4+
5+
// DecodeSQLNullString decodes a sql.NullString
6+
func (dec *Decoder) DecodeSQLNullString(v *sql.NullString) error {
7+
if dec.isPooled == 1 {
8+
panic(InvalidUsagePooledDecoderError("Invalid usage of pooled decoder"))
9+
}
10+
return dec.decodeSQLNullString(v)
11+
}
12+
13+
func (dec *Decoder) decodeSQLNullString(v *sql.NullString) error {
14+
var str string
15+
if err := dec.decodeString(&str); err != nil {
16+
return err
17+
}
18+
v.String = str
19+
v.Valid = true
20+
return nil
21+
}
22+
23+
// DecodeSQLNullInt64 decodes a sql.NullInt64
24+
func (dec *Decoder) DecodeSQLNullInt64(v *sql.NullInt64) error {
25+
if dec.isPooled == 1 {
26+
panic(InvalidUsagePooledDecoderError("Invalid usage of pooled decoder"))
27+
}
28+
return dec.decodeSQLNullInt64(v)
29+
}
30+
31+
func (dec *Decoder) decodeSQLNullInt64(v *sql.NullInt64) error {
32+
var i int64
33+
if err := dec.decodeInt64(&i); err != nil {
34+
return err
35+
}
36+
v.Int64 = i
37+
v.Valid = true
38+
return nil
39+
}
40+
41+
// DecodeSQLNullFloat64 decodes a sql.NullString with the given format
42+
func (dec *Decoder) DecodeSQLNullFloat64(v *sql.NullFloat64) error {
43+
if dec.isPooled == 1 {
44+
panic(InvalidUsagePooledDecoderError("Invalid usage of pooled decoder"))
45+
}
46+
return dec.decodeSQLNullFloat64(v)
47+
}
48+
49+
func (dec *Decoder) decodeSQLNullFloat64(v *sql.NullFloat64) error {
50+
var i float64
51+
if err := dec.decodeFloat64(&i); err != nil {
52+
return err
53+
}
54+
v.Float64 = i
55+
v.Valid = true
56+
return nil
57+
}
58+
59+
// DecodeSQLNullBool decodes a sql.NullString with the given format
60+
func (dec *Decoder) DecodeSQLNullBool(v *sql.NullBool) error {
61+
if dec.isPooled == 1 {
62+
panic(InvalidUsagePooledDecoderError("Invalid usage of pooled decoder"))
63+
}
64+
return dec.decodeSQLNullBool(v)
65+
}
66+
67+
func (dec *Decoder) decodeSQLNullBool(v *sql.NullBool) error {
68+
var b bool
69+
if err := dec.decodeBool(&b); err != nil {
70+
return err
71+
}
72+
v.Bool = b
73+
v.Valid = true
74+
return nil
75+
}

decode_sqlnull_test.go

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
package gojay
2+
3+
import (
4+
"database/sql"
5+
"strings"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestDecodeSQLNullString(t *testing.T) {
12+
testCases := []struct {
13+
name string
14+
json string
15+
expectedNullString sql.NullString
16+
err bool
17+
}{
18+
{
19+
name: "basic",
20+
json: `"test"`,
21+
expectedNullString: sql.NullString{String: "test", Valid: true},
22+
},
23+
{
24+
name: "basic",
25+
json: `"test`,
26+
expectedNullString: sql.NullString{String: "test", Valid: true},
27+
err: true,
28+
},
29+
}
30+
for _, testCase := range testCases {
31+
t.Run(testCase.name, func(t *testing.T) {
32+
nullString := sql.NullString{}
33+
dec := NewDecoder(strings.NewReader(testCase.json))
34+
err := dec.DecodeSQLNullString(&nullString)
35+
if testCase.err {
36+
assert.NotNil(t, err)
37+
} else {
38+
assert.Nil(t, err)
39+
assert.Equal(t, testCase.expectedNullString, nullString)
40+
}
41+
})
42+
}
43+
t.Run(
44+
"should panic because decoder is pooled",
45+
func(t *testing.T) {
46+
dec := NewDecoder(nil)
47+
dec.Release()
48+
defer func() {
49+
err := recover()
50+
assert.NotNil(t, err, "err shouldnt be nil")
51+
assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
52+
}()
53+
_ = dec.DecodeSQLNullString(&sql.NullString{})
54+
assert.True(t, false, "should not be called as decoder should have panicked")
55+
},
56+
)
57+
}
58+
59+
func TestDecodeSQLNullInt64(t *testing.T) {
60+
testCases := []struct {
61+
name string
62+
json string
63+
expectedNullInt64 sql.NullInt64
64+
err bool
65+
}{
66+
{
67+
name: "basic",
68+
json: `1`,
69+
expectedNullInt64: sql.NullInt64{Int64: 1, Valid: true},
70+
},
71+
{
72+
name: "basic",
73+
json: `"test`,
74+
expectedNullInt64: sql.NullInt64{Int64: 1, Valid: true},
75+
err: true,
76+
},
77+
}
78+
for _, testCase := range testCases {
79+
t.Run(testCase.name, func(t *testing.T) {
80+
nullInt64 := sql.NullInt64{}
81+
dec := NewDecoder(strings.NewReader(testCase.json))
82+
err := dec.DecodeSQLNullInt64(&nullInt64)
83+
if testCase.err {
84+
assert.NotNil(t, err)
85+
} else {
86+
assert.Nil(t, err)
87+
assert.Equal(t, testCase.expectedNullInt64, nullInt64)
88+
}
89+
})
90+
}
91+
t.Run(
92+
"should panic because decoder is pooled",
93+
func(t *testing.T) {
94+
dec := NewDecoder(nil)
95+
dec.Release()
96+
defer func() {
97+
err := recover()
98+
assert.NotNil(t, err, "err shouldnt be nil")
99+
assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
100+
}()
101+
_ = dec.DecodeSQLNullInt64(&sql.NullInt64{})
102+
assert.True(t, false, "should not be called as decoder should have panicked")
103+
},
104+
)
105+
}
106+
107+
func TestDecodeSQLNullFloat64(t *testing.T) {
108+
testCases := []struct {
109+
name string
110+
json string
111+
expectedNullFloat64 sql.NullFloat64
112+
err bool
113+
}{
114+
{
115+
name: "basic",
116+
json: `1`,
117+
expectedNullFloat64: sql.NullFloat64{Float64: 1, Valid: true},
118+
},
119+
{
120+
name: "basic",
121+
json: `"test`,
122+
expectedNullFloat64: sql.NullFloat64{Float64: 1, Valid: true},
123+
err: true,
124+
},
125+
}
126+
for _, testCase := range testCases {
127+
t.Run(testCase.name, func(t *testing.T) {
128+
nullFloat64 := sql.NullFloat64{}
129+
dec := NewDecoder(strings.NewReader(testCase.json))
130+
err := dec.DecodeSQLNullFloat64(&nullFloat64)
131+
if testCase.err {
132+
assert.NotNil(t, err)
133+
} else {
134+
assert.Nil(t, err)
135+
assert.Equal(t, testCase.expectedNullFloat64, nullFloat64)
136+
}
137+
})
138+
}
139+
t.Run(
140+
"should panic because decoder is pooled",
141+
func(t *testing.T) {
142+
dec := NewDecoder(nil)
143+
dec.Release()
144+
defer func() {
145+
err := recover()
146+
assert.NotNil(t, err, "err shouldnt be nil")
147+
assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
148+
}()
149+
_ = dec.DecodeSQLNullFloat64(&sql.NullFloat64{})
150+
assert.True(t, false, "should not be called as decoder should have panicked")
151+
},
152+
)
153+
}
154+
155+
func TestDecodeSQLNullBool(t *testing.T) {
156+
testCases := []struct {
157+
name string
158+
json string
159+
expectedNullBool sql.NullBool
160+
err bool
161+
}{
162+
{
163+
name: "basic",
164+
json: `true`,
165+
expectedNullBool: sql.NullBool{Bool: true, Valid: true},
166+
},
167+
{
168+
name: "basic",
169+
json: `"&`,
170+
expectedNullBool: sql.NullBool{Bool: true, Valid: true},
171+
err: true,
172+
},
173+
}
174+
for _, testCase := range testCases {
175+
t.Run(testCase.name, func(t *testing.T) {
176+
nullBool := sql.NullBool{}
177+
dec := NewDecoder(strings.NewReader(testCase.json))
178+
err := dec.DecodeSQLNullBool(&nullBool)
179+
if testCase.err {
180+
assert.NotNil(t, err)
181+
} else {
182+
assert.Nil(t, err)
183+
assert.Equal(t, testCase.expectedNullBool, nullBool)
184+
}
185+
})
186+
}
187+
t.Run(
188+
"should panic because decoder is pooled",
189+
func(t *testing.T) {
190+
dec := NewDecoder(nil)
191+
dec.Release()
192+
defer func() {
193+
err := recover()
194+
assert.NotNil(t, err, "err shouldnt be nil")
195+
assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
196+
}()
197+
_ = dec.DecodeSQLNullBool(&sql.NullBool{})
198+
assert.True(t, false, "should not be called as decoder should have panicked")
199+
},
200+
)
201+
}

0 commit comments

Comments
 (0)