Skip to content

Commit dc92d69

Browse files
authored
Merge pull request #228 from jonomacd/null-handling
**Description**: This adds a bespoke null error to the typed Get functions **Benchmark before change**: ``` BenchmarkJsonParserLarge BenchmarkJsonParserLarge-4 101186 59316 ns/op 0 B/op 0 allocs/op BenchmarkJsonParserMedium BenchmarkJsonParserMedium-4 664688 9127 ns/op 0 B/op 0 allocs/op BenchmarkJsonParserDeleteMedium BenchmarkJsonParserDeleteMedium-4 584113 16541 ns/op 0 B/op 0 allocs/op BenchmarkJsonParserEachKeyManualMedium BenchmarkJsonParserEachKeyManualMedium-4 697446 7584 ns/op 112 B/op 2 allocs/op BenchmarkJsonParserEachKeyStructMedium BenchmarkJsonParserEachKeyStructMedium-4 718255 9049 ns/op 544 B/op 12 allocs/op BenchmarkJsonParserObjectEachStructMedium BenchmarkJsonParserObjectEachStructMedium-4 598053 14774 ns/op 496 B/op 11 allocs/op BenchmarkJsonParserSmall BenchmarkJsonParserSmall-4 5438990 1097 ns/op 0 B/op 0 allocs/op BenchmarkJsonParserEachKeyManualSmall BenchmarkJsonParserEachKeyManualSmall-4 8123079 726.3 ns/op 80 B/op 2 allocs/op BenchmarkJsonParserEachKeyStructSmall BenchmarkJsonParserEachKeyStructSmall-4 5914904 1101 ns/op 184 B/op 7 allocs/op BenchmarkJsonParserObjectEachStructSmall BenchmarkJsonParserObjectEachStructSmall-4 3735968 1712 ns/op 168 B/op 6 allocs/op BenchmarkJsonParserSetSmall BenchmarkJsonParserSetSmall-4 2382969 3151 ns/op 768 B/op 4 allocs/op BenchmarkJsonParserDelSmall BenchmarkJsonParserDelSmall-4 1917996 4370 ns/op 0 B/op 0 allocs/op PASS ok benchmarks 104.655s ``` **Benchmark after change**: ``` BenchmarkJsonParserLarge BenchmarkJsonParserLarge-4 98062 63203 ns/op 0 B/op 0 allocs/op BenchmarkJsonParserMedium BenchmarkJsonParserMedium-4 570456 9970 ns/op 0 B/op 0 allocs/op BenchmarkJsonParserDeleteMedium BenchmarkJsonParserDeleteMedium-4 603286 13375 ns/op 0 B/op 0 allocs/op BenchmarkJsonParserEachKeyManualMedium BenchmarkJsonParserEachKeyManualMedium-4 780256 9199 ns/op 112 B/op 2 allocs/op BenchmarkJsonParserEachKeyStructMedium BenchmarkJsonParserEachKeyStructMedium-4 419198 15755 ns/op 544 B/op 12 allocs/op BenchmarkJsonParserObjectEachStructMedium BenchmarkJsonParserObjectEachStructMedium-4 362432 16357 ns/op 496 B/op 11 allocs/op BenchmarkJsonParserSmall BenchmarkJsonParserSmall-4 3645873 1711 ns/op 0 B/op 0 allocs/op BenchmarkJsonParserEachKeyManualSmall BenchmarkJsonParserEachKeyManualSmall-4 5796182 1012 ns/op 80 B/op 2 allocs/op BenchmarkJsonParserEachKeyStructSmall BenchmarkJsonParserEachKeyStructSmall-4 5057808 1171 ns/op 184 B/op 7 allocs/op BenchmarkJsonParserObjectEachStructSmall BenchmarkJsonParserObjectEachStructSmall-4 5825636 1145 ns/op 168 B/op 6 allocs/op BenchmarkJsonParserSetSmall BenchmarkJsonParserSetSmall-4 3933043 2098 ns/op 768 B/op 4 allocs/op BenchmarkJsonParserDelSmall BenchmarkJsonParserDelSmall-4 2888763 1989 ns/op 0 B/op 0 allocs/op PASS ok benchmarks 93.459s ```
2 parents 2d9d634 + 51af27e commit dc92d69

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

parser.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var (
1818
MalformedValueError = errors.New("Value looks like Number/Boolean/None, but can't find its end: ',' or '}' symbol")
1919
OverflowIntegerError = errors.New("Value is number, but overflowed while parsing")
2020
MalformedStringEscapeError = errors.New("Encountered an invalid escape sequence in a string")
21+
NullValueError = errors.New("Value is null")
2122
)
2223

2324
// How much stack space to allocate for unescaping JSON strings; if a string longer
@@ -311,7 +312,7 @@ func searchKeys(data []byte, keys ...string) int {
311312
case '[':
312313
// If we want to get array element by index
313314
if keyLevel == level && keys[level][0] == '[' {
314-
var keyLen = len(keys[level])
315+
keyLen := len(keys[level])
315316
if keyLen < 3 || keys[level][0] != '[' || keys[level][keyLen-1] != ']' {
316317
return -1
317318
}
@@ -322,7 +323,7 @@ func searchKeys(data []byte, keys ...string) int {
322323
var curIdx int
323324
var valueFound []byte
324325
var valueOffset int
325-
var curI = i
326+
curI := i
326327
ArrayEach(data[i:], func(value []byte, dataType ValueType, offset int, err error) {
327328
if curIdx == aIdx {
328329
valueFound = value
@@ -1191,6 +1192,9 @@ func GetString(data []byte, keys ...string) (val string, err error) {
11911192
}
11921193

11931194
if t != String {
1195+
if t == Null {
1196+
return "", NullValueError
1197+
}
11941198
return "", fmt.Errorf("Value is not a string: %s", string(v))
11951199
}
11961200

@@ -1213,6 +1217,9 @@ func GetFloat(data []byte, keys ...string) (val float64, err error) {
12131217
}
12141218

12151219
if t != Number {
1220+
if t == Null {
1221+
return 0, NullValueError
1222+
}
12161223
return 0, fmt.Errorf("Value is not a number: %s", string(v))
12171224
}
12181225

@@ -1229,6 +1236,9 @@ func GetInt(data []byte, keys ...string) (val int64, err error) {
12291236
}
12301237

12311238
if t != Number {
1239+
if t == Null {
1240+
return 0, NullValueError
1241+
}
12321242
return 0, fmt.Errorf("Value is not a number: %s", string(v))
12331243
}
12341244

@@ -1246,6 +1256,9 @@ func GetBoolean(data []byte, keys ...string) (val bool, err error) {
12461256
}
12471257

12481258
if t != Boolean {
1259+
if t == Null {
1260+
return false, NullValueError
1261+
}
12491262
return false, fmt.Errorf("Value is not a boolean: %s", string(v))
12501263
}
12511264

parser_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,12 @@ var getIntTests = []GetTest{
913913
path: []string{"c"},
914914
isErr: true,
915915
},
916+
{
917+
desc: `null test`,
918+
json: `{"a": "b", "c": null}`,
919+
path: []string{"c"},
920+
isErr: true,
921+
},
916922
}
917923

918924
var getFloatTests = []GetTest{
@@ -936,6 +942,12 @@ var getFloatTests = []GetTest{
936942
path: []string{"c"},
937943
isErr: true,
938944
},
945+
{
946+
desc: `null test`,
947+
json: `{"a": "b", "c": null}`,
948+
path: []string{"c"},
949+
isErr: true,
950+
},
939951
}
940952

941953
var getStringTests = []GetTest{
@@ -1006,6 +1018,12 @@ var getStringTests = []GetTest{
10061018
path: []string{"["},
10071019
isFound: false,
10081020
},
1021+
{
1022+
desc: `null test`,
1023+
json: `{"c": null}`,
1024+
path: []string{"c"},
1025+
isErr: true,
1026+
},
10091027
}
10101028

10111029
var getUnsafeStringTests = []GetTest{
@@ -1087,6 +1105,13 @@ var getBoolTests = []GetTest{
10871105
isFound: true,
10881106
data: true,
10891107
},
1108+
{
1109+
desc: `null test`,
1110+
json: `{"a": "b", "c": null}`,
1111+
path: []string{"c"},
1112+
isFound: false,
1113+
isErr: true,
1114+
},
10901115
}
10911116

10921117
var getArrayTests = []GetTest{
@@ -1408,7 +1433,7 @@ func TestArrayEach(t *testing.T) {
14081433
}
14091434

14101435
func TestArrayEachWithWhiteSpace(t *testing.T) {
1411-
//Issue #159
1436+
// Issue #159
14121437
count := 0
14131438
funcError := func([]byte, ValueType, int, error) { t.Errorf("Run func not allow") }
14141439
funcSuccess := func(value []byte, dataType ValueType, index int, err error) {

0 commit comments

Comments
 (0)