diff --git a/feature_any.go b/feature_any.go index 87b0e29..6841622 100644 --- a/feature_any.go +++ b/feature_any.go @@ -13,6 +13,7 @@ type Any interface { Size() int Keys() []string IterateObject() (func() (string, Any, bool), bool) + IterateArray() (func() (Any, bool), bool) } type baseAny struct {} @@ -29,6 +30,10 @@ func (any *baseAny) IterateObject() (func() (string, Any, bool), bool) { return nil, false } +func (any *baseAny) IterateArray() (func() (Any, bool), bool) { + return nil, false +} + func (iter *Iterator) ReadAny() Any { return iter.readAny(nil) } diff --git a/feature_any_array.go b/feature_any_array.go index 94912e6..d0c8131 100644 --- a/feature_any_array.go +++ b/feature_any_array.go @@ -125,3 +125,59 @@ func (any *arrayLazyAny) Size() int { any.fillCache() return len(any.cache) } + + +func (any *arrayLazyAny) IterateArray() (func() (Any, bool), bool) { + remaining := any.remaining + if len(remaining) == len(any.buf) { + iter := any.parse() + iter.head++ + c := iter.nextToken() + if c != ']' { + iter.unreadByte() + v := iter.readAny(iter) + any.cache = append(any.cache, v) + remaining = iter.buf[iter.head:] + any.remaining = remaining + } else { + remaining = nil + any.remaining = nil + return nil, false + } + } + if len(any.cache) == 0 { + return nil, false + } + arr := any.cache + nextValue := arr[0] + i := 1 + return func() (Any, bool) { + value := nextValue + if i < len(arr) { + // read from cache + nextValue = arr[i] + i++ + return value, true + } else { + // read from buffer + iter := any.iter + if iter == nil { + iter = NewIterator() + any.iter = iter + } + iter.ResetBytes(remaining) + c := iter.nextToken() + if c == ',' { + nextValue = iter.readAny(iter) + any.cache = append(any.cache, nextValue) + remaining = iter.buf[iter.head:] + any.remaining = remaining + return value, true + } else { + remaining = nil + any.remaining = nil + return value, false + } + } + }, true +} diff --git a/feature_any_object.go b/feature_any_object.go index 6fc929d..d18c9d7 100644 --- a/feature_any_object.go +++ b/feature_any_object.go @@ -146,6 +146,7 @@ func (any *objectLazyAny) Keys() []string { } return keys } + func (any *objectLazyAny) IterateObject() (func() (string, Any, bool), bool) { if any.cache == nil { any.cache = map[string]Any{} diff --git a/jsoniter_array_test.go b/jsoniter_array_test.go index c7bcab7..0d12b01 100644 --- a/jsoniter_array_test.go +++ b/jsoniter_array_test.go @@ -67,6 +67,19 @@ func Test_read_two_element_array_as_any(t *testing.T) { should.Equal(2, any.Size()) } +func Test_read_array_with_any_iterator(t *testing.T) { + should := require.New(t) + any, err := UnmarshalAnyFromString("[1,2]") + should.Nil(err) + var element Any + var elements []int + for next, hasNext := any.IterateArray(); hasNext; { + element, hasNext = next() + elements = append(elements, element.ToInt()) + } + should.Equal([]int{1, 2}, elements) +} + func Test_invalid_array(t *testing.T) { _, err := UnmarshalAnyFromString("[") if err == nil || err == io.EOF {