Skip to content

Array and guess #214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
- Adding ability to stop array processing by generating an error
- Adding ability to guess datatype of the JSON data
  • Loading branch information
stephane-moreau committed Oct 7, 2020
commit 340cc1c6d71866ff60e4dc26073dfaab54ce10ad
15 changes: 11 additions & 4 deletions parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ func searchKeys(data []byte, keys ...string) int {
var valueFound []byte
var valueOffset int
var curI = i
ArrayEach(data[i:], func(value []byte, dataType ValueType, offset int, err error) {
ArrayEach(data[i:], func(value []byte, dataType ValueType, offset int, err error) error {
if curIdx == aIdx {
valueFound = value
valueOffset = offset
Expand All @@ -327,6 +327,7 @@ func searchKeys(data []byte, keys ...string) int {
}
}
curIdx += 1
return nil
})

if valueFound == nil {
Expand Down Expand Up @@ -508,7 +509,7 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
level++

var curIdx int
arrOff, _ := ArrayEach(data[i:], func(value []byte, dataType ValueType, offset int, err error) {
arrOff, _ := ArrayEach(data[i:], func(value []byte, dataType ValueType, offset int, err error) error {
if arrIdxFlags&bitwiseFlags[curIdx+1] != 0 {
for pi, p := range paths {
if pIdxFlags&bitwiseFlags[pi+1] != 0 {
Expand All @@ -530,6 +531,7 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
}

curIdx += 1
return nil
})

if pathsMatched == len(paths) {
Expand All @@ -555,6 +557,11 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str
return -1
}

func GuessValueType(data []byte, offset int) (ValueType, error) {
_, dataType, _, err := getType(data, offset)
return dataType, err
}

// Data types available in valid JSON data.
type ValueType int

Expand Down Expand Up @@ -920,7 +927,7 @@ func internalGet(data []byte, keys ...string) (value []byte, dataType ValueType,
}

// ArrayEach is used when iterating arrays, accepts a callback function with the same return arguments as `Get`.
func ArrayEach(data []byte, cb func(value []byte, dataType ValueType, offset int, err error), keys ...string) (offset int, err error) {
func ArrayEach(data []byte, cb func(value []byte, dataType ValueType, offset int, err error) error, keys ...string) (offset int, err error) {
if len(data) == 0 {
return -1, MalformedObjectError
}
Expand All @@ -930,7 +937,7 @@ func ArrayEach(data []byte, cb func(value []byte, dataType ValueType, offset int
return -1, MalformedJsonError
}

offset = nT+1
offset = nT + 1

if len(keys) > 0 {
if offset = searchKeys(data, keys...); offset == -1 {
Expand Down
34 changes: 22 additions & 12 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ import (
var activeTest = ""

func toArray(data []byte) (result [][]byte) {
ArrayEach(data, func(value []byte, dataType ValueType, offset int, err error) {
ArrayEach(data, func(value []byte, dataType ValueType, offset int, err error) error {
result = append(result, value)
return nil
})

return
}

func toStringArray(data []byte) (result []string) {
ArrayEach(data, func(value []byte, dataType ValueType, offset int, err error) {
ArrayEach(data, func(value []byte, dataType ValueType, offset int, err error) error {
result = append(result, string(value))
return nil
})

return
Expand Down Expand Up @@ -1363,7 +1365,7 @@ func TestArrayEach(t *testing.T) {
mock := []byte(`{"a": { "b":[{"x": 1} ,{"x":2},{ "x":3}, {"x":4} ]}}`)
count := 0

ArrayEach(mock, func(value []byte, dataType ValueType, offset int, err error) {
ArrayEach(mock, func(value []byte, dataType ValueType, offset int, err error) error {
count++

switch count {
Expand All @@ -1386,14 +1388,18 @@ func TestArrayEach(t *testing.T) {
default:
t.Errorf("Should process only 4 items")
}
return nil
}, "a", "b")
}

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

switch count {
Expand All @@ -1412,17 +1418,18 @@ func TestArrayEachWithWhiteSpace(t *testing.T) {
default:
t.Errorf("Should process only 3 items")
}
return nil
}

type args struct {
data []byte
cb func(value []byte, dataType ValueType, offset int, err error)
cb func(value []byte, dataType ValueType, offset int, err error) error
keys []string
}
tests := []struct {
name string
args args
wantErr bool
name string
args args
wantErr bool
}{
{"Array with white space", args{[]byte(` ["AAA", "BBB", "CCC"]`), funcSuccess, []string{}}, false},
{"Array with only one character after white space", args{[]byte(` 1`), funcError, []string{}}, true},
Expand All @@ -1440,11 +1447,14 @@ func TestArrayEachWithWhiteSpace(t *testing.T) {
}

func TestArrayEachEmpty(t *testing.T) {
funcError := func([]byte, ValueType, int, error) { t.Errorf("Run func not allow") }
funcError := func([]byte, ValueType, int, error) error {
t.Errorf("Run func not allow")
return nil
}

type args struct {
data []byte
cb func(value []byte, dataType ValueType, offset int, err error)
cb func(value []byte, dataType ValueType, offset int, err error) error
keys []string
}
tests := []struct {
Expand Down Expand Up @@ -1675,7 +1685,7 @@ func TestEachKey(t *testing.T) {
{"arrInt", "[3]"},
{"arrInt", "[5]"}, // Should not find last key
{"nested"},
{"arr", "["}, // issue#177 Invalid arguments
{"arr", "["}, // issue#177 Invalid arguments
{"a\n", "b\n"}, // issue#165
}

Expand Down