diff --git a/parser.go b/parser.go index 57ede94..88c904f 100644 --- a/parser.go +++ b/parser.go @@ -320,7 +320,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 @@ -330,6 +330,7 @@ func searchKeys(data []byte, keys ...string) int { } } curIdx += 1 + return nil }) if valueFound == nil { @@ -517,7 +518,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 _, ok = arrIdxFlags[curIdx]; ok { for pi, p := range paths { if pIdxFlags[pi] { @@ -539,6 +540,7 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str } curIdx += 1 + return nil }) if pathsMatched == len(paths) { @@ -564,6 +566,19 @@ func EachKey(data []byte, cb func(int, []byte, ValueType, error), paths ...[]str return -1 } +// GuessValueType : returns the type of the next JSON piece in data stream +// Does not ensure that the whole data is a valid JSON +func GuessValueType(data []byte) (ValueType, error) { + + offset := nextToken(data) + if offset == -1 { + return NotExist, MalformedJsonError + } + + _, dataType, _, err := getType(data, offset) + return dataType, err +} + // Data types available in valid JSON data. type ValueType int @@ -976,7 +991,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 } @@ -1031,11 +1046,11 @@ func ArrayEach(data []byte, cb func(value []byte, dataType ValueType, offset int } if t != NotExist { - cb(v, t, offset+o-len(v), e) + e = cb(v, t, offset+o-len(v), e) } if e != nil { - break + return offset + o - len(v), e } offset += o diff --git a/parser_test.go b/parser_test.go index 11b3e66..38f1263 100644 --- a/parser_test.go +++ b/parser_test.go @@ -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 @@ -989,15 +991,15 @@ var getStringTests = []GetTest{ isErr: true, }, { - desc: `empty array index`, - json: `[""]`, - path: []string{"[]"}, + desc: `empty array index`, + json: `[""]`, + path: []string{"[]"}, isFound: false, }, { - desc: `malformed array index`, - json: `[""]`, - path: []string{"["}, + desc: `malformed array index`, + json: `[""]`, + path: []string{"["}, isFound: false, }, } @@ -1375,7 +1377,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 { @@ -1398,14 +1400,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 { @@ -1424,11 +1430,12 @@ 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 { @@ -1452,11 +1459,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 {